API

[API ] Stream API를 이용한 전체 근무 일자 구하기

easy-6 2025. 1. 26. 20:27

stream()메소드는 Java8부터 도입된 기능, 스트림을 사용하면 함수형 프로그래밍 방식으로 처리할 수 있음. 

즉 반복문(for, while 등)을 사용하지 않고 데이터를 처리할 수 있음

아래는 나의 근무시간 계산에 대한 코드이다. 

// DailyWorkTimeServiceImpl.java
package com.springCommunity.service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.springCommunity.dao.DailyWorkTimeDAO;
import com.springCommunity.vo.DailyWorkTimeVO;


@Service // 서비스 계층의 컴포넌트 의미
 public class DailyWorkTimeServiceImpl implements DailyWorkTimeService { // DailyWorkTimeService의 구현 클래스 의미 

    @Autowired // 의존성 자동 주입 
    private DailyWorkTimeDAO dailyWorkTimeDAO;

	// 절대 변하지 않는 고정된 값 설정함
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public List<Map<String, Object>> getDetailedWorkTimeList(String userId) {
        List<DailyWorkTimeVO> workTimes = dailyWorkTimeDAO.selectDetailedList(userId);

        return workTimes.stream()
            .map(workTime -> {
                Map<String, Object> details = new HashMap<>();

                // Extract date from check-in time
                details.put("date", workTime.getCheck_in_time().split(" ")[0]);
                details.put("checkInTime", workTime.getCheck_in_time());
                details.put("checkOutTime", workTime.getCheck_out_time());

                // Calculate work duration if both check-in and check-out times exist
                if (workTime.getCheck_in_time() != null && workTime.getCheck_out_time() != null) {
                    LocalDateTime checkIn = LocalDateTime.parse(workTime.getCheck_in_time(), formatter);
                    LocalDateTime checkOut = LocalDateTime.parse(workTime.getCheck_out_time(), formatter);

                    long workMinutes = Duration.between(checkIn, checkOut).toMinutes();
                    details.put("workDuration", workMinutes);
                } else {
                    details.put("workDuration", 0L);
                }

                return details;
            })
            .collect(Collectors.toList());
    }
}

 

1️⃣

private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

 

  • DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")을 사용해서 "yyyy-MM-dd HH:mm:ss" 형식의 문자열을 LocalDateTime으로 변환

 

2️⃣

 List<DailyWorkTimeVO> workTimes = dailyWorkTimeDAO.selectDetailedList(userId);

DB에서 userId에 해당하는 출근 시간, 퇴근 시간 , 아이디를 가져옴 

 

 

 

3️⃣

return workTimes.stream()
    .map(workTime -> {
        Map<String, Object> details = new HashMap<>();

        // 날짜 추출
        details.put("date", workTime.getCheck_in_time().split(" ")[0]);
        details.put("checkInTime", workTime.getCheck_in_time());
        details.put("checkOutTime", workTime.getCheck_out_time());

        // 근무 시간 계산
        if (workTime.getCheck_in_time() != null && workTime.getCheck_out_time() != null) {
            LocalDateTime checkIn = LocalDateTime.parse(workTime.getCheck_in_time(), formatter);
            LocalDateTime checkOut = LocalDateTime.parse(workTime.getCheck_out_time(), formatter);

            long workMinutes = Duration.between(checkIn, checkOut).toMinutes();
            details.put("workDuration", workMinutes);
        } else {
            details.put("workDuration", 0L);
        }

        return details;
    })
    .collect(Collectors.toList());
// 1 stream API를 사용한 경우 
// stream()을 사용하여 반복문을 대체할 수 있음 
workTimes.stream() // worktimes 리스트를 스트림으로 변화 시킴 

// 2  stream API 대신 for문을 사용한 경우 
for (DailyWorkTimeVO worktime : workTimes)

위의 1과 2는 같음 

 

 

4️⃣

.map(workTime -> {
        Map<String, Object> details = new HashMap<>();

        // 날짜 추출
        details.put("date", workTime.getCheck_in_time().split(" ")[0]);
        details.put("checkInTime", workTime.getCheck_in_time());
        details.put("checkOutTime", workTime.getCheck_out_time());

        // 근무 시간 계산
        if (workTime.getCheck_in_time() != null && workTime.getCheck_out_time() != null) {
            LocalDateTime checkIn = LocalDateTime.parse(workTime.getCheck_in_time(), formatter);
            LocalDateTime checkOut = LocalDateTime.parse(workTime.getCheck_out_time(), formatter);

            long workMinutes = Duration.between(checkIn, checkOut).toMinutes();
            details.put("workDuration", workMinutes);
        } else {
            details.put("workDuration", 0L);
        }

        return details;
    })
       .collect(Collectors.toList());


for (DailyWorkTimeVO workTime : workTimes) {
    Map<String, Object> details = new HashMap<>();

    // 날짜 추출
    details.put("date", workTime.getCheck_in_time().split(" ")[0]);
    details.put("checkInTime", workTime.getCheck_in_time());
    details.put("checkOutTime", workTime.getCheck_out_time());

    // 근무 시간 계산
    if (workTime.getCheck_in_time() != null && workTime.getCheck_out_time() != null) {
        LocalDateTime checkIn = LocalDateTime.parse(workTime.getCheck_in_time(), formatter);
        LocalDateTime checkOut = LocalDateTime.parse(workTime.getCheck_out_time(), formatter);

        long workMinutes = Duration.between(checkIn, checkOut).toMinutes();
        details.put("workDuration", workMinutes);
    } else {
        details.put("workDuration", 0L);
    }

    result.add(details);
}

위의 stream()함수와 for문은 동일한 역할을 가진다. 

▶️ stream()

  • stream()의 경우는 workTimes. stream()으로 반복문을 돌리며,   .map(workTime ->{ 변환 로직}).collect(Collectors.toList()); 코드를 통해서 전체를 반복하며, map에 담긴 내용을 list로 결과를 반환한다고 볼 수 있음

아래는 예시이다.

{
    "date": "2023-10-01",
    "checkInTime": "2023-10-01 09:00:00",
    "checkOutTime": "2023-10-01 18:00:00",
    "workDuration": 540
}

 

▶️ for문

  • for문의 경우는 List<Map<String , Object>> 타입의 result라는 변수를 생성하고 시작한다.향상된 for문을 돌며 details라는 map을 생성 후 map에 날짜, 출근 시간 ,퇴근 시간, 계산한 근무 시간을 담고, list에 add를 통해서 담는다 . 

아래는 예시이다. 

{
    "date": "2023-10-01",
    "checkInTime": "2023-10-01 09:00:00",
    "checkOutTime": "2023-10-01 18:00:00",
    "workDuration": 540
}

 

5️⃣

 

 

 

6️⃣

 

 

*.mapToLong >> 스트림의 각 요소를 long타입으로 변환시키는 중간연산자 

  • 여기서 detail은 workTimeDetails 리스트의 각 요소인 Map<String, Object> 객체입니다.
  • detail.get("workDuration")은 Map에서 workDuration 키에 해당하는 값을 가져옵니다.
    • workDuration은 근무 시간(분 단위)을 나타내는 값입니다.
    • (long)으로 캐스팅하는 이유는 Map의 값이 Object 타입이기 때문에 long 타입으로 명시적으로 변환해줍니다.