최근 한 프로젝트에서 로직이 복잡한 배치 프로그램에서 에러가 났다.
디버깅하려고 보니 Stream을 이용해 코딩한 것.
일반 for문으로 코드를 수정한 뒤에 디버깅을 해 오류를 해결했다.
Stream과 일반 for문의 차이를 메모하고자 작성하는 포스팅.
for문 사용 | Stream 사용 | |
장점 |
|
|
단점 |
|
|
디버깅 | 쉬움 | 어려움 |
추천 사용법 | 복잡한 조건 or 상태 변경 | 단순 필터/맵핑 |
예제로 비교해 보자.
공통 샘플 데이터
List<Map<String, Object>> people = new ArrayList<>();
people.add(Map.of("name", "철수", "age", 28, "team", "A", "score", 85));
people.add(Map.of("name", "영희", "age", 32, "team", "B", "score", 90));
people.add(Map.of("name", "민수", "age", 40, "team", "A", "score", 70));
people.add(Map.of("name", "지영", "age", 29, "team", "B", "score", 95));
people.add(Map.of("name", "수지", "age", 35, "team", "C", "score", 88));
1. if문 조건에 따른 로직(println)
//--# for문
for (Map<String, Object> person : people) {
Integer age = (Integer) person.get("age");
if (age >= 30) {
System.out.println(person.get("name"));
}
}
//--# Stream
people.stream()
.filter(p -> (Integer) p.get("age") >= 30)
.map(p -> (String) p.get("name"))
.forEach(System.out::println);
2. 값 변경 없는 정렬 - "score" 기준 내림차순
//--# for문
people.sort((p1, p2) -> ((Integer) p2.get("score")) - ((Integer) p1.get("score")));
//--# Stream
List<Map<String, Object>> sorted =
people.stream()
.sorted((p1, p2) -> ((Integer) p2.get("score")) - ((Integer) p1.get("score")))
.collect(Collectors.toList());
3. 값 변경 있는 정렬 - "grade" 추가 후 "score" 기준 내림차순
//--# for문 : 원본 리스트 변경함
for (Map<String, Object> person : people) {
int score = (Integer) person.get("score");
String grade;
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else {
grade = "C";
}
person.put("grade", grade);
}
// 정렬 (score 기준 내림차순)
people.sort((p1, p2) -> ((Integer) p2.get("score")) - ((Integer) p1.get("score")));
//--# Stream : 새 리스트 생성 (collect)
List<Map<String, Object>> updatedAndSorted = people.stream()
.peek(person -> {
int score = (Integer) person.get("score");
String grade;
if (score >= 90) grade = "A";
else if (score >= 80) grade = "B";
else grade = "C";
person.put("grade", grade); // 값 변경
})
.sorted((p1, p2) -> ((Integer) p2.get("score")) - ((Integer) p1.get("score")))
.collect(Collectors.toList());
✅ stream의 peek()의 원래 목적 : 값을 바꾸거나 외부에 영향을 주는 용도가 아님.
peek()은 중간 연산자로, Stream 안에서 "디버깅용 또는 가볍게 훑어보는 용도"로 만들어졌다.
stream.peek(System.out::println)
그렇지만 실무에서는 편해서 자주 쓴다고 한다.
stream
.peek(e -> e.put("grade", "A")) // Map에 새로운 값 추가
.collect(Collectors.toList());
4. 그룹핑 - team별 그룹
//--# for문
Map<String, List<Map<String, Object>>> grouped = new HashMap<>();
for (Map<String, Object> person : people) {
String team = (String) person.get("team");
grouped.computeIfAbsent(team, k -> new ArrayList<>()).add(person);
}
//--# Stream
Map<String, List<Map<String, Object>>> grouped =
people.stream()
.collect(Collectors.groupingBy(p -> (String) p.get("team")));
5. 집계 (전체 score 합계 & 평균)
//--# for문
int sum = 0;
for (Map<String, Object> person : people) {
sum += (Integer) person.get("score");
}
double avg = (double) sum / people.size();
//--# Stream
int sum = people.stream()
.mapToInt(p -> (Integer) p.get("score"))
.sum();
double avg = people.stream()
.mapToInt(p -> (Integer) p.get("score"))
.average()
.orElse(0.0);
'JAVA' 카테고리의 다른 글
[JAVA] 자바 정규식 사용해서 특수분자 치환할 때 에러 (0) | 2022.06.17 |
---|---|
[Spring Boot] build.gradle dependencies 문법 (0) | 2022.05.26 |
[Spring boot] Gradle Refresh 안 될 때 (0) | 2022.05.25 |
[java] 어노테이션(Annotations) @Size @Length @Column(length)의 차이점 (0) | 2021.10.12 |
[Spring] @Transactional 작동 안 할 때 확인해봐야 할 것 (0) | 2021.08.25 |