본문 바로가기
IT/Java

[Java] List Grouping 하는 방법

by eddie_factory 2025. 2. 10.
반응형

작업을 하다보면 DB검색 시 Group를 묶어서 조회하는 경우도 있지만 서비스에서 Grouping을 사용해야 할 경우도 있다.

 

List Grouping 하는 방법.

Person이라는 Object리스트를  성별, 도시별로 그룹핑한다고 가정할 시...

 

객체 정의

public class Person {
    private String name;
    private String sex;  // "남성", "여성"
    private String city;

    // 생성자
    public Person(String name, String sex, String city) {
        this.name = name;
        this.sex = sex;
        this.city = city;
    }

    // Getter 메서드
    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public String getCity() {
        return city;
    }

    @Override
    public String toString() {
        return String.format("Person{name='%s', sex='%s', city='%s'}", name, sex, city);
    

 

Grouping

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        // Person 리스트 생성
        List<Person> people = Arrays.asList(
            new Person("Alice", "여성", "Seoul"),
            new Person("Bob", "남성", "Busan"),
            new Person("Charlie", "남성", "Seoul"),
            new Person("David", "남성", "Busan"),
            new Person("Eve", "여성", "Seoul"),
            new Person("Frank", "남성", "Incheon"),
            new Person("Grace", "여성", "Incheon"),
            new Person("Hank", "남성", "Seoul"),
            new Person("Ivy", "여성", "Busan"),
            new Person("Jack", "남성", "Incheon")
        );

        // 성별 -> 도시별 그룹화
        Map<String, Map<String, List<Person>>> groupedPeople = people.stream()
                .collect(Collectors.groupingBy(
                        Person::getSex,   // 1차 그룹화: 성별
                        Collectors.groupingBy(Person::getCity) // 2차 그룹화: 도시별
                ));

        // 결과 출력
        groupedPeople.forEach((sex, cityMap) -> {
            System.out.println("[" + sex + "]");
            cityMap.forEach((city, personList) -> {
                System.out.println("  " + city + ": " + personList);
            });
        });
    }
}

steam Collectors.groupingBy를 활용해 원하는 조건대로 리스트를 그룹핑할 수 있다.

 

다른 방법으로는 Grouping할 객체를 선언해서 객체로 Grouping 할 수 있다.

import java.util.Objects;

public class Grouping {
    private String sex;
    private String city;

    // 생성자
    public Grouping(String sex, String city) {
        this.sex = sex;
        this.city = city;
    }

    // Getter 메서드
    public String getSex() {
        return sex;
    }

    public String getCity() {
        return city;
    }

    // equals() & hashCode() 오버라이딩 (Map 키로 사용하려면 필수)
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Grouping grouping = (Grouping) obj;
        return Objects.equals(sex, grouping.sex) &&
               Objects.equals(city, grouping.city);
    }

    @Override
    public int hashCode() {
        return Objects.hash(sex, city);
    }

    @Override
    public String toString() {
        return String.format("Grouping{sex='%s', city='%s'}", sex, city);
    }
}

 

public class Main {
    public static void main(String[] args) {
        // Person 리스트 생성
        List<Person> people = Arrays.asList(
            new Person("Alice", "여성", "Seoul"),
            new Person("Bob", "남성", "Busan"),
            new Person("Charlie", "남성", "Seoul"),
            new Person("David", "남성", "Busan"),
            new Person("Eve", "여성", "Seoul"),
            new Person("Frank", "남성", "Incheon"),
            new Person("Grace", "여성", "Incheon"),
            new Person("Hank", "남성", "Seoul"),
            new Person("Ivy", "여성", "Busan"),
            new Person("Jack", "남성", "Incheon")
        );

        // Map<Grouping, List<Person>> 형태로 그룹화
        Map<Grouping, List<Person>> groupedPeople = people.stream()
                .collect(Collectors.groupingBy(person -> new Grouping(person.getSex(), person.getCity())));

        // 결과 출력
        groupedPeople.forEach((grouping, personList) -> {
            System.out.println(grouping + " => " + personList);
        });
    }
}

Collectors.groupingBy에 만들어둔 Grouping 객체를 선언해 그룹핑할 수 있다.


다만 객체를 선언해 사용할 경우는 equals와 hashcode를 Override 해줘야 한다.

 

equals와 hashcode를 Override하는 이유.

grouping을 g1, g2로 선언하고 같은 데이터를 넣엇을때..

  • HashMap은 기본적으로 객체의 참조 주소값을 비교하므로 g2는 g1과 다른 객체로 간주됨
  • 결과적으로 g2로 데이터를 검색할 때 null이 반환됨

 

equals()와 hashCode()를 오버라이딩하지 않으면 → Map에서 동일한 값을 가지는 키로 검색이 불가능 (null 반환).
equals()와 hashCode()를 정확히 구현하면 → Map에서 동일한 값을 가진 객체를 같은 키로 인식하고 정상적으로 조회 가능.
객체를 Map의 키로 사용할 때는 equals()와 hashCode()를 항상 오버라이딩하는 것이 필수.
반응형

'IT > Java' 카테고리의 다른 글

Error와 Exception  (0) 2021.04.08
Primitive Type과 Reference Type  (0) 2021.04.07
JAVA 제네릭(Generic) 이해하기  (0) 2021.04.06
JVM의 이해  (0) 2021.04.05
String, StringBuffer, StringBuilder 특징 및 차이점  (0) 2020.03.24

댓글