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 타입으로 명시적으로 변환해줍니다.
'API' 카테고리의 다른 글
| [API] chart.js의 레이블과 데이터의 동기화를 맞추기 위한 stream API (0) | 2025.02.07 |
|---|