Java8 Collectors 가이드
Java8 Collectors 가이드
1. 개요
스트림의 마지막 단계에서 사용되는 Collectors에 대해 설명합니다.
2. Stream.collect() Method
Stream.collect () 는 Java 8의 Stream API에서 제공하는 메소드입니다 . Stream 인스턴스에 보관 된 데이터 요소에 대해 변경 가능한 Grouping 작업 (요소를 일부 데이터 구조로 재 포장 및 추가 논리 적용, 연결 등)을 수행 할 수 있습니다.
이러한 작업 Grouping 작업은 Collector 인터페이스를 통해 제공됩니다 .
3. Collectors
모든 구현은 Collectors 클래스 에서 찾을 수 있으며, 가독성을 높이기 위해 다음 static import를 사용하는 것이 일반적입니다.
import static java.util.stream.Collectors.*;
아니면 개별적으로 선언할수 있습니다.
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;
여기서는 아래의 리스트를 가지고 설명합니다.
List<String> givenList = Arrays.asList("a","bb","ccc","dd");
3.1. Collectors.toList()
toList() 메소드는 Stream의 모든 요소를 List 인스턴스로 변환하는 데 사용할 수 있습니다 . 이 메소드를 사용하여 특정 List 구현을 없습니다. 다른 형태의 컬렉션으로 반환하려면 toCollection() 메소드를 사용해야 합니다.
List<String> result = givenList.stream().collect(toList());
3.2. Collectors.toSet()
toSet() 메소드는 Stream의 모든 요소를 Set 인스턴스로 변환하는 데 사용할 수 있습니다 .
Set<String> set = givenList.stream().collect(toSet());
Set는 중복 요소를 허요하지 않으며, 컬렉션에 서로 같은 요소가 포함 된 경우 결과 Collection에 한개만 생성됩니다.
List<String> listWithDuplicates
= Arrays.asList("a", "bb", "c", "d", "bb");
Set<String> result
= listWithDuplicates.stream().collect(toSet());
assertThat(result).hasSize(4);
3.3. Collectors.toCollection()
toSet 및 toList 는 해당 Collection을 지정할수 없습니다. 사용자 정의한 Collection을 사용하려면 toCollection 메소드를 사용해야합니다 .
LinkedList로 Stream을 변환하는 예제:
List<String> result
= givenList.stream().collect(toCollection(LinkedList::new));
변경이 불가능한 Collection에서는 사용이 불가능하며, 이런 경우 collectingAndThen() 메소드를 사용하여 사용자정의 Collector를 사용해야 합니다.
3.4. Collectors.toMap()
toMap Collector는 Stream의 요소를 Map으로 변환하는데 사용합니다. 변환하기 위해서는 keyMapper와 valueMapper 함수를 제공해야합니다.
- keyMapper
- valueMapper
keyMapper 는 Stream의 요소를 추출하는 key로써 사용되고, valueMapper 는 주어진 key Stream의 요소를 반환하는데 사용합니다.
문자열을 key로 지정하고 문자열의 길이를 value로 저장하는 Map으로 반환하는 Collector 예시:
Map<String, Integer> result = givenList.stream()
.collect(toMap(Function.identity(), String::length));
3.5. Collectors.collectingAndThen()
collectingAndThen() 은 수집 이 끝난 직후 결과에 대해 다른 작업을 수행 할 수 있는 Collector입니다.
Stream 요소를 List 인스턴스 로 수집 한 다음 결과를 ImmutableList 로 변환합니다 .
List<String> result = givenList.stream()
.collect(collectingAndThen(toList(), ImmutableList::copyOf))
3.6. Collectors.joining()
Stream 요소 를 결합하는 데 join()을 사용할 수 있습니다 .
다음을 수행하여 함께 참여할 수 있습니다.
String result = givenList.stream()
.collect(joining());
결과는 다음과 같습니다.
"abbcccdd"
사용자 정의 구분 기호 지정할 수 있습니다.
String result = givenList.stream()
.collect(joining(" "));
결과는 다음과 같습니다.
"a bb ccc dd"
접두사 , 접미사를 지정할 수 있습니다.
String result = givenList.stream()
.collect(joining(" ", "PRE-", "-POST"));
결과는 다음과 같습니다.
"PRE-a bb ccc dd-POST"
3.7. Collectors.counting()
counting() 은 모든 Stream 요소를 간단히 카운팅 할 수 있습니다 .
String result = givenList.stream().collect(joining(" "));
3.8. Collectors.summarizingDouble/Long/Int()
summarizingDouble / Long / Int 메소드 는 Stream 요소에서 숫자 데이터에 대한 통계 정보를 제공합니다.
다음을 수행하여 문자열 길이에 대한 정보를 얻을 수 있습니다.
DoubleSummaryStatistics result = givenList.stream()
.collect(summarizingDouble(String::length));
이 경우 다음이 적용됩니다.
assertThat(result.getAverage()).isEqualTo(2);
assertThat(result.getCount()).isEqualTo(4);
assertThat(result.getMax()).isEqualTo(3);
assertThat(result.getMin()).isEqualTo(1);
assertThat(result.getSum()).isEqualTo(8);
3.9. Collectors.averagingDouble/Long/Int()
averagingDouble / Long / Int 는 추출 된 요소의 평균을 반환합니다.
다음을 수행하여 평균 문자열 길이를 얻을 수 있습니다.
Double result = givenList.stream()
.collect(averagingDouble(String::length));
3.10. Collectors.summingDouble/Long/Int()
summingDouble / Long / Int 는 추출 된 요소의 합계를 반환합니다.
다음을 수행하여 모든 문자열 길이의 합계를 얻을 수 있습니다.
Double result = givenList.stream()
.collect(summingDouble(String::length));
3.11. Collectors.maxBy()/minBy()
maxBy / MinBy 수집기 는 제공된 스트림 의 가장 큰 / 가장 작은 요소를 반환합니다 .
다음을 수행하여 가장 큰 요소를 선택할 수 있습니다.
Optional<String> result = givenList.stream()
.collect(maxBy(Comparator.naturalOrder()));
반환 된 값은 Optional 인스턴스에 래핑됩니다 . 이로 인해 사용자는 Optional이 비어있는 케이스를 고려해야 합니다.
3.12. Collectors.groupingBy()
groupingBy 메소드는 주어진 조건에 따라 오브젝트를 그룹화하고 결과를 Map 인스턴스 에 저장하는 데 사용됩니다 .
문자열 길이로 그룹화하고 그룹화 결과를 Set 인스턴스 에 저장하는 예제:
Map<Integer, Set<String>> result = givenList.stream()
.collect(groupingBy(String::length, toSet()));
처리결과
assertThat(result)
.containsEntry(1, newHashSet("a"))
.containsEntry(2, newHashSet("bb", "dd"))
.containsEntry(3, newHashSet("ccc"));
groupingBy 메소드 의 두 번째 인수 는 Collector 이며 원하는 Collector 를 자유롭게 사용
3.13. Collectors.partitioningBy()
PartitioningBy 는 스트림 요소를 부울 값을 키로, 컬렉션을 값으로 저장 하는 Map 으로 반환 하는 groupingBy 의 특수한 경우입니다 .
Map<Boolean, List<String>> result = givenList.stream()
.collect(partitioningBy(s -> s.length() > 2))
처리 결과는 다음과 같습니다.
{false=["a", "bb", "dd"], true=["ccc"]}
3.14. Collectors.teeing()
지금까지 배운 콜렉터를 사용하여 주어진 스트림 에서 최대 및 최소 수를 찾으십시오 .
List<Integer> numbers = Arrays.asList(42, 4, 2, 24);
Optional<Integer> min = numbers.stream().collect(minBy(Integer::compareTo));
Optional<Integer> max = numbers.stream().collect(maxBy(Integer::compareTo));
// do something useful with min and max
서로 다른 두 수집기를 사용하고 그 결과를 결합하여 만듭니다. Java 12 이전에는 이러한 사용 사례를 다루기 위해 주어진 스트림에서 두 번 작업하고 중간 결과를 임시 변수에 저장 한 다음 그 결과를 결합해야했습니다.
다행히도 Java 12는 이러한 단계를 대신하여 내장 콜렉터를 제공합니다. 두 콜렉터와 결합기 기능을 제공하기 만하면됩니다.
numbers.stream().collect(teeing(
minBy(Integer::compareTo), // The first collector
maxBy(Integer::compareTo), // The second collector
(min, max) -> // Receives the result from those collectors and combines them
));
4. 마무리
이제 JPA에서 Stream과 Collector를 심층적으로 사용할 수 있습니다.
작성자 : eyebora32
참조 : https://www.baeldung.com/java-8-collectors
Written with StackEdit.
댓글
댓글 쓰기