명령형 코드에서는 다중 루프와 조건문을 추가하며 가독성과 유지보수성이 크게 떨어진다. 함수형 프로그래밍에서는 필요한 컬렉터를 쉽게 추가할 수 있다.
toList는 스트림의 모든 요소를 리스트로 수집한다.
List<Transaction> transactions = transactionStream.collect(Collectors.toList());
Collectors에서 제공하는 메서드의 기능은 크게 세 가지로 구분할 수 있다.
컬렉터로 스트림의 항목을 컬렉션으로 재구성할 수 있다. 좀 더 쉽게 말하자면 컬렉터로 스트림의 모든 항목을 하나의 결과로 합칠 수 있다.
long howManyDishes = menu.stream().collect(Collectors.counting());
// 불필요한 과정 생략
long howManyDishes = menu.stream().count();
예제에서, 메뉴에서 칼로리가 가장 높은 요리를 찾는다고 가정할 때, Collectors.maxBy, Collectors.minBy 두 개의 메서드를 이용해서 스트림의 최댓값과 최솟값을 계산할 수 있다.
두 컬렉터는 스트림의 요소를 비교하는 데 사용할 Comparator를 인수로 받는다.
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCalorieDish = menu.stream()
.collect(maxBy(dishCaloriesComparator));
스트림에 있는 객체의 숫자 필드의 합계나 평균 등을 반환하는 연산에도 리듀싱 기능이 자주 사용된다. ⇒ 요약
연산
Collectors 클래스는 Collectors.summingInt라는 요약 팩토리 메서드를 제공한다.
summingInt는 객체를 int로 매핑하는 함수를 인수로 받는다. 인수로 전달된 함수는 객체를 int로 매핑한 컬렉터를 반환한다.
int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));
스트림의 요소 수를 계산하고, 최댓값. 최솟값을 찾고, 합계와 평균을 계산하는 것 들 중 두 개 이상의 연산을 한 번에 수행해야 할 때도 있는데, 이럴때는 팩토리 메서드 summarizingInt가 반환하는 컬렉터를 사용할 수 있다.
IntSummaryStatistics menuStatistics = menu.stream().collect(summarizingInt(Dish::getCalories));
위 코드를 실행하면 모든 정보가 수집된다.
컬렉터에 joining 팩토리 메서드를 이용하면 스트림의 각 객체에 toString 메서드를 호출해서 추출한 모든 문자열을 하나의 문자열로 연결해서 반환한다.
String shortMenu = menu.stream().map(Dish::getName).collect(joining());
joining 메서드는 내부적으로 StringBuilder를 이용해서 문자열을 하나로 만든다.
연결된 두 요소 사이에 구분 문자열을 넣을 수 있도록 오버로드된 joining 팩토리 메서드도 있다.
String shortMenu = menu.stream().map(Dish::getName).collect(joining(", "));
모든 컬렉터는 reducing 팩토리 메서드로도 정의할 수 있다.
int totalCalories = menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));
reducing은 인수 세 개를 받는다.
추가 설명 들어갈 예정
~2.15
팩토리 메서드 Collectors.groupingBy를 이용해서 메뉴를 그룹화할 수 있다.
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));
스트림의 각 요리에서 Dish.Type과 일치하는 모든 요리를 추출하는 함수를 groupingBy 메서드로 전달했다.
⇒ 이 함수를 기준으로 스트림이 그룹화되므로 이를 분류 함수
라고도 부른다.
요소를 그룹화한 다음에는 각 결과 그룹의 요소를 조작하는 연산이 필요하다.