IT

Java Stream Grouping - 데이터 그룹화와 집계

채보 2024. 1. 15. 00:03

안녕하세요. 
오늘은 쉽지만 맨날 검색하고 있는 Groupingby에 대해 사용법을 간략하게 정리해봅니다. 
groupingBy 메서드는 데이터를 그룹화하는데 유용하게 활용되는 메소드입니다.

1. groupingBy 메서드 소개
groupingBy 메서드는 자바 스트림을 그룹화하는 데 사용됩니다.

예를 들어, 리스트의 객체를 특정 속성에 따라 그룹화하거나 집계할 수 있습니다.

잊지 말아야 할껀 groupingBy는 Map으로 리턴된다는 점!!

List<Person> people = // 데이터 초기화

Map<Gender, List<Person>> peopleByGender = people.stream()
    .collect(Collectors.groupingBy(Person::getGender));


위의 예제에서는 Person 객체를 성별에 따라 그룹화하여 Map<Gender, List<Person>>으로 얻을 수 있습니다.



2. 다중 그룹화
groupingBy 메서드는 여러 수준의 그룹화도 지원합니다.

예를 들어, 성별과 나이에 따라 그룹화하는 경우 다음과 같이 할 수 있습니다.

리턴타입을 보면 그룹화 된 데이터는 map으로 리턴되는거 보이시죠?

하지만 이렇게까지 사용하는 경우는 잘 없는거 같아요.

List<Person> people = // 데이터 초기화

Map<Gender, Map<Integer, List<Person>>> peopleByGenderAndAge = people.stream()
    .collect(Collectors.groupingBy(Person::getGender,
             Collectors.groupingBy(Person::getAge)));

 


3. 그룹화 후 집계
그룹화된 데이터에 대해 집계를 수행할 수도 있습니다.

주로 평균을 내거나 합계를 구하곤 하지요.

예를 들어, 각 그룹의 평균 나이를 계산하려면 다음과 같이 할 수 있습니다.

List<Person> people = // 데이터 초기화

Map<Gender, Double> averageAgeByGender = people.stream()
    .collect(Collectors.groupingBy(Person::getGender,
             Collectors.averagingInt(Person::getAge)));

 


4. map to list
그룹화한 데이터를 다시 가공하여 List로 만드는 작업도 많이 하는 작업이지요.

예를 들어, 아래 예제는 나이로 그룹화한 후에 상위 2 그룹의 목록을 구하는 예제입니다. 

List<Person> people = // 데이터 초기화

List<Person> recommendSizeResultList = people.stream()
                .collect(Collectors.groupingBy(Person::getAge())) // 나이로 그룹화
                .entrySet() // 그룹화한 key set
                .stream()
                .sorted((a, b) -> b.getKey().compareTo(a.getKey())) // 역순정렬
                .limit(2)	// 상위 2그룹 추출
                .flatMap(entry -> entry.getValue().stream()) // value list를 합치기
                .collect(Collectors.toList());



5. 마무리

처음 보면 어색할 수 있지만 위 예제와 같은 로직을 for문과 if문으로 구현한다면 더 복잡해지고 라인은 길어질 수 밖에 없습니다. 

stream을 이용하면 복잡한 데이터셋에서 간단하고 가독성 있게 그룹화 및 집계를 수행할 수 있습니다.