•
함수형 프로그래밍에서는 ‘무엇’을 원하는지 직접 명시할 수 있어서 어떤 방법으로 이를 얻을지는 신경 쓸 필요가 없다.
•
다음 예제에서 collect 메서드로 Collectors 인터페이스 구현을 전달했다. Collector 인터페이스 구현은 스트림의 요소를 어떤 식으로 도출할지 지정한다.
Map<Currency, List<Transaction>> transactionsByCurrencies = transactions.stream().collect(groupingBy(Transaction::getCuurency));
Java
복사
•
여기서는 groupingBy를 이용해서 통화를 키로 하고 밸류는 트랜잭션 리스트로 하는 맵을 만들라는 동작을 수행한다.
•
다수준으로 그룹화를 수행할 때, 명령형 프로그래밍과 함수형 프로그래밍의 차이점이 더욱 두드러진다.
•
명령형에서는 문제를 해결하는 과정에서 다중 루프와 조건문을 추가하며 가독성과 유지보수성이 떨어진다.
•
함수형 프로그래밍에서는 필요한 컬렉터를 쉽게 추가할 수 있다.
1. 고급 리듀싱 기능을 수행하는 컬렉터
•
함수형 API의 또 다른 장점은 높은 수준의 조합성과 재사용성이다.
•
collect로 결과를 수집하는 과정을 간단하면서도 유연하게 정의할 수 있다는 점이 컬렉터의 최대 강점이다.
•
스트림에 collect를 호출하면 스트림의 요소에 리듀싱 연산이 수행된다. 보통 함수를 요소로 변환할 때는 컬렉터를 적용하며 최종 결과를 저장하는 자료구조에 값을 누적한다.
◦
예를 들어 이전 트랜잭션 그룹화 예제에서 변환 함수는 각 트랜잭션에서 통화를 추출한 다음에 통화를 키로 사용해서 트랜잭션 자체를 결과 맵에 누적했다.
•
통화 예제에서 보여주는 것처럼 Collectors 인터페이스의 메서드를 어떻게 구현하느냐에 따라 스트림에 어떤 리듀싱 연산을 수행할지 결정된다.
•
Collectors 유틸리티 클래스는 자주 사용하는 컬렉터 인스턴스를 손쉽게 생성할 수 있는 정적 팩토리 메서드를 제공한다.
◦
예를 들어 우리가 자주 사용했던 toList를 꼽을 수 있다. toList는 스트림의 모든 요소를 리스트로 수집한다.
2. 미리 정의된 컬렉터
•
미리 정의된 컬렉터, 즉 groupingBy 같이 Collectors 클래스에서 제공하는 팩토리 메서드의 기능이다.
•
Collectors에서 제공하는 메서드의 기능은 크게 세 가지로 구분될 수 있다.
◦
스트림 요소를 하나의 값으로 리듀스하고 요약
▪
트랜잭션 리스트에서 트랜잭션 총합을 찾는 등의 다양한 계산을 수행할 때 이들 컬렉터를 유용하게 사용할 수 있다.
◦
요소 그룹화
▪
이전 예제를 다수준으로 그룹화하거나 각각의 결과 서브그룹에 추가로 리듀싱 연산을 적용할 수 있도록 다양한 컬렉터를 조합하는 방법도 배울 것이다.
◦
요소 분할
▪
또한 그룹의 특별한 연산인 분할도 설명한다. 분할은 한 개의 인수를 받아 불리언으로 반환하는 함수, 즉 프레디케이트를 그룹화 함수로 사용한다.