💡 주의 : Collector는 인터페이스이고, Collectors는 클래스이다.
정리 !
// collect() 메서드의 선언부
// 매개변수가 1개인 collect()
Object collect(Collector collector) // Collector를 구현한 클래스의 객체를 매개변수로 필요로한다.
// 매개변수가 3개인 collect()
Object collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
// Stream을 List로 변환해서 반환 받는 예제
List<String> names = stuStream.map(Student::getName)
.collect(Collectors.toList());
// Stream을 특정 컬렉션으로 반환 받는 예제(Stream -> ArrayList)
ArrayList<String> list = names.stream()
.collect(Collectors.toCollection(ArrayList::new));
// Stream을 Map으로 반환 받는 예제
Map<String, Person> map = personStream.
.collect(Collectors.toMap(p->p.getRegId(), p->p));
💡 Map의 경우 키와 값의 쌍으로 저장해야하기 때문에 객체의 어떤 필드를 키와 값으로 사용할지 지정해야 한다.
// Stream을 배열로 변환하는 예제 - 1
Student[] stuNames = studentStream.toArray(Student::new); // OK
// Stream을 배열로 변환하는 예제 - 2
Student[] stuNames = studentStream.toArray(); // Object를 반환하므로 형변환을 해주어야 한다(에러)
Student[] stuNames = (Student[])studentStream.toArray(); // OK
// Stream을 배열로 반환하는 예제 - 3
Object[] stuNames = studentStream.toArray(); // OK (Object를 반환한다.)
// 개수 구하기 - counting()
long count = stuStream.collect(Collectors.counting());
// 최대값 구하기 - max()
Optional<Student> topStudent = stuStream.
collect(Collectors.maxBy(Comparator.comparingInt(Student::getTotalScore)));
// 합계 구하기 - summingInt()
long totalScore = stuSTream.collect(Collectors.summingInt(Student::getTotalScore));
// IntSummaryStatistics 반환 받기 - summarizingInt()
IntSummaryStatistics stat = stuStream.
.collect(Collectors.summarizingInt(Student::getTotalScore));
// IntStream으로 collect()를 이용한 리듀싱 예제 1 - 최대 값 구하기
Optional<Integer> max = intStream.boxed().collect(Collectors.reducing(Integer::max));
// IntStream으로 collect()를 이용한 리듀싱 예제 2 - 합계 구하기
long sum = intStream.boxed().collect(Collectors.reducing(0, (a,b) -> a + b));
// Stream으로 collect()를 이용한 리듀싱 예제 3 - 합계 구하기
int grandTotal = stuStream.collect(Collectors.reducing(0, Student::getTotalScore, Integer::sum));
// joining()을 사용한 일반 결합
String studentNames = stuStream.map(Student::getName).collect(joining());
// joining()을 사용한 구분자 지정 결합
String studentNames = stuStream.map(Student::getName).collect(joining(","));
// joining()을 사용한 구분자, 접두사, 접미사 지정 결합
String studentNames = stuStream.map(Student::getName).collect(joining(",", "[", "]"));
// Collectors는 static import 되었다고 가정하고 Collectors를 생략한다.
// 학생들을 성별로 나누어 List에 담는 예제 - 단순 분할
Map<Boolean, List<Student>> stuBySex = stuStream
.collect(
partitioningBy(Student::isMale)); // 학생들을 성별로 분할
List<Student> maleStudent = stuBySex.get(true); // Map에서 남학생 목록을 가져온다.
List<Student> femaleStudent = stuBySex.get(false); // Map에서 여학생 목록을 가져온다.
// counting()을 사용한 학생 수 구하기 예제
Map<Boolean, Long> stuNumBySex = stuStream
.collect(partitioningBy(Student::isMale, counting()));
// maxBy를 사용한 남학생 1등과 여학생 1등 구하기 예제
Map<Boolean, Optional<Student>> topScoreBySex = stuStream
.collect(partitioningBy(Student::isMale,
maxBy(comparingInt(Student::getScore))
)
);
💡maxBy( )는 반환타입이 Optional<T>이다. Optional대신 객체로 반환받으려면, collectingAndThen( )과
Optional :: get을 함께 사용하면 된다.
// Optional::get 사용예제
// Collectors는 static import 되었다고 가정하고 Collectors를 생략한다.
Map<Boolean, Student> topScoreBySex = stuStream
.collect(
partitioningBy(Student::isMale,
collectingAndThen(
maxBy(comparingInt(Student::getScore)), Optional::get
)
)
);
// 성적이 150점 아래인 학생들을 불합격처리 하는 예제 - 이중 분할
Map<Boolean, Map<Boolean, List<Student>>> failedStuBySex = stuStream
.collect(
partitioningBy(Student::isMale,
partitioningBy(s -> s.getScore() < 150)
)
);