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.

댓글

주간 인기글

SPA(Sigle Page Applications) 란 무엇인가?

[앱 디자인] 디자인 가이드 만들기 - 안드로이드

[ubuntu] 신규 계정에 sudo 권한 추가하기

Nodejs 날짜 관련 유용한 moment.js

[Android] Parcelable 에 대한 쉬운 이해