위 코드는 스트림 코드를 가장한 반복적 코드로, 스트림 API의 이점을 살리지 못하고 있다.
forEach : 스트림이 수행한 연산 결과를 보여줄 때 사용하고, 계산할 때는 사용하지 말자.
(스트림 계산 결과를 기존 컬렉션에 추가하는 등 다른 용도로도 쓸 수 있다.)
forEach 내부에서 외부 상태(freq)를 수정하는 람다를 실행하고 있으므로 순수 함수가 아닌 것을 볼 수 있다. 또한, 같은 기능의 반복문보다 코드가 길고, 읽기 어려우며, 유지보수에도 좋지 않다.
다음 예는 위 예제 코드를 올바르게 작성한 것이다.
스트림 API를 제대로 사용했으며, 코드도 짧고 명확하다.
Collector
java.util.stream.Collectors : 자주 사용하는 API 제공
Collectors 의 멤버를 정적 임포트(static import)해 사용하면, 스트림 가독성이 좋아짐
스트림의 원소를 손쉽게 컬렉션으로 생성 가능
최종 처리(스트림 종료 작업)
toList()
toMap()
toMap(keyMapper, valueMapper) : 각 원소가 고유한 키에 매핑되어 있을 때 적합
인수 3개 받는 toMap : 어떤 키와 그 키에 연관된 원소들 중 하나를 골라 연관 짓는 맵을 만들때 유용
마지막에 쓴 값을 취하는 수집기
네번째 인수로 맵 팩터리(EnumMap, TreeMap, HashMap)를 받는 toMap
groupingBy()
입력으로 분류 함수(classifier)를 받고 출력으로 원소들을 카테고리별로 모아 놓은 맵을 담은 수집기 반환한다.
```java List productList = Arrays.asList(new Product(23, "potatoes"), new Product(14, "orange"), new Product(13, "lemon"), new Product(23, "bread"), new Product(13, "sugar"));