List<Dish> menu = Dish.getDishes();
List<String> names = menu.stream() // 요리 리스트에서 스트림 얻기
.filter(dish -> dish.getCalories() > 300) // 중간 연산
.map(Dish::getName) // 중간 연산
.limit(3) // 중간 연산
.collect(Collectors.toList()); // 스트림을 리스트로 변환
위 예제를 두 가지 연산으로 구분해 보겠다.
중간 연산 | 최종 연산 |
filter, map, limit | collect |
파이프라인을 형성한다 | 파이프라인을 실행한 다음에 닫는다 |
출처: Modern Java in Action
1. 다른 스트림을 반환한다.2. 여러 중간 연산을 연결할 수 있다.3. ⭐️ 게으르다. (lazy)
단말 연산을 스트림 파이프라인에 실행하기 전까지는 아무 연산도 수행하지 않는다는 뜻이다.
중간 연산을 합친 다음에 합쳐진 중간 연산을 최종 연산으로 한 번에 처리하기 때문이다.
예제
List<Dish> menu = Dish.getDishes();
List<String> names = menu.stream()
.filter(dish -> {
System.out.println("filtering:" + dish.getName());
return dish.getCalories() > 300;
}) // 필터링한 요리명을 출력한다.
.map(dish -> {
System.out.println("mapping:" + dish.getName());
return dish.getName();
}) // 추출한 요리명을 출력한다.
.limit(3)
.collect(Collectors.toList());
System.out.println(names);
실행결과 💻
filtering:pork
mapping:pork
filtering:beef
mapping:beef
filtering:chicken
mapping:chicken
[pork, beef, chicken]
게으른 특성으로 몇 가지 최적화 효과를 얻을 수 있다.
1. 300 칼로리가 넘는 요리는 여러 개지만 오직 처음 3개만 선택됐다. 이는 limit 연산 그리고 쇼트서킷이라는 기법이다.
2. filter, map은 다른 연산이지만 한 과정으로 병합됐다. 이 기법을 루프 퓨전이라고 한다.
1. 최종 연산은 스트림 파이프라인에서 결과를 도출한다.
2. 보통 최종 연산에 의해 List, Integer, void 등 스트림 이외의 결과가 반환된다.
(forEach가 대표적인 void를 반환하는 최종 연산이다.)
List<Dish> menu = Dish.getDishes();
menu.stream().forEach(System.out::println);
연산 | 형식 | 반환 형식 | 목적 |
forEach | 최종 연산 | void | 스트림의 각 요소를 소비하면서 람다를 적용한다. |
count | 최종 연산 | long (generic) | 스트림의 요소 개수를 반환한다. |
collect | 최종 연산 | 스트림을 없애고 리스트, 맵, 정수 형식의 컬렉션을 만든다. |
1. 질의를 수행할 (컬렉션 같은) 데이터 소스
2. 스트림 파이프라인을 구성할 중간 연산 연결
3. 스트림 파이프라인을 실행하고 결과를 만들 최종 연산
[모던 자바 인 액션] 스트림 takeWhile( ), dropWhile( ), limit( ), skip( )로 슬라이싱하기 (2) | 2022.06.30 |
---|---|
[모던 자바 인 액션] 스트림 distinct(), filter() 사용법 (0) | 2022.06.30 |
[모던 자바 인 액션] 컬렉션 vs 스트림 (Collection vs Stream) (0) | 2022.06.26 |
[모던 자바 인 액션] 🏞 스트림? 그게 뭐야? 도대체 왜 사용하는거야? (0) | 2022.06.19 |
댓글 영역