Java

Java 8 groupingBy Collector 예제

기록만이살길 2020. 6. 25. 01:20
반응형

Java 8 groupingBy Collector 예제

123123

1. 소개

이 기사에서는 다양한 예제를 사용하여 groupingBy 콜렉터가 작동 하는 방식을 살펴 본다 .

이 기사에서 다루는 내용을 이해하려면 Java 8 기능에 대한 기본 지식이 필요합니다. Java 8 Streams 소개Java 8 Collectors 안내서를 살펴볼 수 있습니다 .

2. GroupingBy Collectors

Java 8 Stream API를 사용하면 선언적인 방식으로 데이터 모음을 처리 할 수 ​​있습니다.

정적 팩토리 메소드 인 Collectors.groupingBy ()Collectors.groupingByConcurrent () 는 SQL 언어 의 ' GROUP BY' 절 과 유사한 기능을 제공 합니다. 속성을 기준으로 객체를 그룹화하고 결과를 Map 인스턴스 에 저장하는 데 사용됩니다 .

오버로드 된 groupingBy 메소드 :

  • 메소드 매개 변수로 분류 기능 사용 :
static <T,K> Collector<T,?,Map<K,List<T>>> 
  groupingBy(Function<? super T,? extends K> classifier)
  • 메소드 매개 변수로 분류 함수 및 두 번째 콜렉터 사용 :
static <T,K,A,D> Collector<T,?,Map<K,D>>
  groupingBy(Function<? super T,? extends K> classifier, 
    Collector<? super T,A,D> downstream)
  • 분류 함수, 공급 업체 메소드 ( 최종 결과를 포함 할 Map 구현 제공 ) 및 메소드 매개 변수로 두 번째 콜렉터를 사용하십시오.
static <T,K,D,A,M extends Map<K,D>> Collector<T,?,M>
  groupingBy(Function<? super T,? extends K> classifier, 
    Supplier<M> mapFactory, Collector<? super T,A,D> downstream)

2.1. 코드 설정 예

groupingBy ()의 사용법을 보여주기 위해 BlogPost 클래스를 정의 해 봅시다 ( 블로그 포스트 객체 스트림을 사용할 것입니다 ).

class BlogPost {
    String title;
    String author;
    BlogPostType type;
    int likes;
}

BlogPostType :

enum BlogPostType {
    NEWS,
    REVIEW,
    GUIDE
}

목록블로그 게시물의 객체 :

List<BlogPost> posts = Arrays.asList( ... );

유형작성자 속성 의 조합으로 게시물을 그룹화하는 데 사용될 Tuple 클래스 도 정의 해 보겠습니다 .

class Tuple {
    BlogPostType type;
    String author;
}

2.2. 단일 열로 간단한 그룹화

분류 함수를 매개 변수로만 사용하는 가장 간단한 groupingBy 메서드 부터 시작하겠습니다 . 분류 함수는 스트림의 각 요소에 적용됩니다. 함수가 반환 한 값은 groupingBy 콜렉터 에서 가져 오는 맵의 키로 사용됩니다 .

블로그 게시물 목록에서 블로그 게시물을 유형별로 그룹화하려면 다음을 수행하십시오.

Map<BlogPostType, List<BlogPost>> postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType));

2.3. 복잡한 키 유형으로 그룹화

분류 함수는 스칼라 또는 문자열 값만 리턴하도록 제한되지 않습니다. 필요한 equalshashcode 메소드를 구현하는 한 결과 맵의 키는 모든 오브젝트가 될 수 있습니다 .

Tuple 인스턴스 에서 결합 된 유형작성자 별로 목록의 블로그 게시물을 기준으로 그룹화하려면 다음을 수행하십시오 .

Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
  .collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));

2.4. 리턴 된 값 유형 수정

groupingBy 의 두 번째 과부하 는 추가 두 번째 수집기 (다운 스트림 수집기)를 가져와 첫 번째 수집기의 결과에 적용됩니다.

다운 스트림 콜렉터가 아닌 분류 함수 만 지정하면 toList () 콜렉터가 뒤에서 사용됩니다.

하자가 사용 toSet () 다운 스트림 콜렉터로 수집을하고 얻을 설정 블로그 게시물을 (대신의 목록 ) :

Map<BlogPostType, Set<BlogPost>> postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, toSet()));

2.5. 여러 필드로 그룹화

다운 스트림 콜렉터의 다른 적용은 첫 번째 그룹의 결과를 기준으로 2 차 그룹화를 수행하는 것입니다.

먼저 BlogPost 목록작성자 별로 그룹화 한 다음 유형별로 그룹화하려면 다음을 수행하십시오 .

Map<String, Map<BlogPostType, List>> map = posts.stream()
  .collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType)));

2.6. 그룹화 된 결과에서 평균 얻기

다운 스트림 콜렉터를 사용하여 분류 함수의 결과에 집계 함수를 적용 할 수 있습니다.

각 블로그 게시물 유형에 대한 평균 좋아요 수를 찾으려면 다음을 수행하십시오 .

Map<BlogPostType, Double> averageLikesPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes)));

2.7. 그룹화 된 결과에서 합계 얻기

유형좋아요 총합을 계산하려면 다음을 수행하십시오 .

Map<BlogPostType, Integer> likesPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes)));

2.8. 그룹화 된 결과에서 최대 또는 최소 얻기

우리가 수행 할 수있는 또 다른 집계는 최대 수의 좋아요를 가진 블로그 게시물을 얻는 것입니다.

Map<BlogPostType, Optional<BlogPost>> maxLikesPerPostType = posts.stream()
  .collect(groupingBy(BlogPost::getType,
  maxBy(comparingInt(BlogPost::getLikes))));

마찬가지로 minBy 다운 스트림 콜렉터를 적용 하여 최소한의 좋아요 수로 블로그 게시물을 가져올 수 있습니다.

있습니다 maxByminBy 수집 계정으로이 적용되는 컬렉션이 비어있을 수있는 가능성을. 이것이 맵의 값 유형이 Optional 이유 입니다.

2.9. 그룹화 된 결과의 속성에 대한 요약 얻기

수집기 API 제공 우리가 같은 시간에 수, 합계, 최소, 최대 및 숫자 속성의 평균을 계산해야 할 때 경우에 사용할 수있는 요약하는 수집기.

각기 다른 유형에 대한 블로그 게시물의 likes 속성에 대한 요약을 계산해 보겠습니다.

Map<BlogPostType, IntSummaryStatistics> likeStatisticsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, 
  summarizingInt(BlogPost::getLikes)));

각 유형 의 IntSummaryStatistics 객체에는 likes 속성 의 개수, 합계, 평균, 최소 및 최대 값이 포함됩니다 . double 및 long 값에 대한 추가 요약 개체가 있습니다.

2.10. 그룹화 된 결과를 다른 유형으로 맵핑

분류 기능의 결과에 매핑 다운 스트림 콜렉터를 적용하여 더 복잡한 집계를 수행 할 수 있습니다 .

각 블로그 게시물 유형 에 대한 게시물 제목을 연결해 보겠습니다 .

Map<BlogPostType, String> postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, 
  mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]"))));

여기서 우리가 한 일은 각 BlogPost 인스턴스를 제목 에 매핑 한 다음 게시물 제목 스트림을 연결된 String으로 줄이는 것 입니다. 이 예제에서 값 의 유형은 기본 목록 유형 과도 다릅니다 .

2.11. 맵타입 그룹핑 반환

groupingBy 콜렉터를 사용하는 경우 리턴 된 Map 유형에 대해 가정 할 수 없습니다 . 우리의 유형에 대해 구체적으로하려면 지도 우리가 다음 우리는의 제 3 변형 사용하여 그룹에서 싶어 groupingBy의 우리의 유형을 변경할 수있는 방법 지도를 통과하여 지도 공급 기능을.

하자가 검색 EnumMap는을 는 전달하여 EnumMap는의 받는 공급 기능을 groupingBy의 방법 :

EnumMap<BlogPostType, List<BlogPost>> postsPerType = posts.stream()
  .collect(groupingBy(BlogPost::getType, 
  () -> new EnumMap<>(BlogPostType.class), toList()));

3. 동시성 Grouping by Collector

groupingBy 와 유사하게 멀티 코어 아키텍처를 활용 하는 groupingByConcurrent 콜렉터가 있습니다. 이 콜렉터에는 groupingBy 콜렉터 의 각각의 오버로드 된 메소드와 정확히 동일한 인수를 취하는 3 개의 오버로드 된 메소드가 있습니다 . 그러나 groupingByConcurrent 콜렉터 의 리턴 유형은 ConcurrentHashMap 클래스 의 인스턴스 또는 그 서브 클래스 여야 합니다.

그룹화 작업을 동시에 수행하려면 스트림이 병렬이어야합니다.

ConcurrentMap<BlogPostType, List<BlogPost>> postsPerType = posts.parallelStream()
  .collect(groupingByConcurrent(BlogPost::getType));

Map 공급자 함수를 groupingByConcurrent 콜렉터 에 전달하기로 선택한 경우 함수가 ConcurrentHashMap 또는 서브 클래스를 리턴하는지 확인해야 합니다.

4. Java 9 추가

Java 9는 groupingBy 와 함께 작동하는 두 개의 새로운 수집기를 가져 왔습니다. 이에 대한 자세한 정보는 여기를 참조하십시오 .

5. 결론

이 기사에서는 Java 8 Collectors API 에서 제공 하는 groupingBy 콜렉터 사용법에 대한 몇 가지 예를 보았습니다 .

groupingBy 를 사용하여 속성 중 하나를 기반으로 요소 스트림을 분류하는 방법과 분류 결과를 추가로 수집, 변경 및 최종 컨테이너로 줄일 수있는 방법을 살펴 보았습니다 .

이 기사에 대한 예제의 완전한 구현은 GitHub 프로젝트 에서 찾을 수 있습니다 .

참고

https://www.baeldung.com/java-groupingby-collector

반응형

'Java' 카테고리의 다른 글

Keycloak의 로그인 페이지 사용자 정의  (0) 2021.09.20
Java 8 Stream 불변 Collection  (0) 2020.06.27
Java 8 Collectors 베스트 예제  (0) 2020.06.24
Java 8 Functional Interfaces  (0) 2020.06.22
Java 8 Stream findFirst findAny 차이  (0) 2020.06.21