반응형
collect()메소드는 단순히 요소를 수집하는 기능 외 컬렉션의 요소들을 그룹핑해서 Map객체를 생성하는 기능도 제공한다.
Collectors의 groupingBy() 또는 groupingByConcurrent()가 리턴하는 Collector를 매개값으로 대입하면 사용할 수 있다.
groupingBy()는 Map객체를 리턴하며, groupingByConcurrent는 ConcurrentMap을 리턴한다.
Collectors의 static method
// With a classification function as the method parameter:
// T를 K로 매핑하고, K키에 저장된 List에 T를 저장한 Map 생성
static <T,K> Collector<T,?,Map<K,List<T>>>
groupingBy(Function<? super T,? extends K> classifier)
// With a classification function and a second collector as method parameters:
// T를 K로 매핑하고, K키에 저장된 D객체에 T를 누적한 Map 생성
static <T,K,A,D> Collector<T,?,Map<K,D>>
groupingBy(Function<? super T,? extends K> classifier,
Collector<? super T,A,D> downstream)
// With a classification function, a supplier method (that provides the Map implementation that will contain the end result), and a second collector as method parameters:
// T를 K로 매핑하고 Supplier가 제공하는 Map에서 K키에 저장된 D객체에 T를 누적
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)
Case1. groupingBy(Function<? super T,? extends K> classifier)
학생들을 성별로 그룹핑하고 나서, 같은 그룹에 속하는 학생 List를 생성한 후,
성별을 Key로, 학생 List를 Value로 갖는 Map을 생성한다.
public class StudentMockData {
public static final List<Student> totalList =
Arrays.asList(
new Student("깡냉", 10, Student.Sex.MALE),
new Student("손생", 8, Student.Sex.MALE),
new Student("크리스챤", 5, Student.Sex.MALE),
new Student("원숭이", 5, Student.Sex.MALE),
new Student("완두콩", 0, Student.Sex.FEMALE),
new Student("완두콩2", 0, Student.Sex.FEMALE)
);
}
public class GroupingExam1 {
public static void main(String[] args) {
List<Student> totalList = StudentMockData.totalList;
Stream<Student> totalStream = totalList.stream();
Function<Student, Student.Sex> classifier = Student::getSex;
Collector<Student, ?, Map<Student.Sex, List<Student>>> collector =
Collectors.groupingBy(classifier);
Map<Student.Sex, List<Student>> mapBySex = totalStream.collect(collector);
System.out.println(mapBySex);
// 위의 코드와 같음
mapBySex = totalList.stream()
.collect(Collectors.groupingBy(Student::getSex));
}
}
Student.Sex(FEMALE, MALE)이 Key가되고, 그룹핑된 List<Student>가 Value가 되는 Map을 얻을 수 있다.
Case2. groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)
학생들을 점수별로 그룹핑하고 나서, 같은 그룹에 속하는 학생들의 이름 List를 생성한 후,
점수를 Key로 이름 List를 Value로 갖는 Map을 생성한다.
public static final List<Student> totalList2 =
Arrays.asList(
new Student("깡냉", 10, Student.Sex.MALE, Student.City.Incheon),
new Student("손생", 8, Student.Sex.MALE, Student.City.Seoul),
new Student("크리스챤", 5, Student.Sex.MALE, Student.City.Incheon),
new Student("원숭이", 5, Student.Sex.MALE, Student.City.Seoul),
new Student("완두콩", 0, Student.Sex.FEMALE, Student.City.Incheon),
new Student("완두콩2", 0, Student.Sex.FEMALE, Student.City.Incheon)
);
public class GroupingExam2 {
public static void main(String[] args) {
List<Student> totalList = StudentMockData.totalList2;
Stream<Student> totalStream = totalList.stream();
Function<Student, Student.City> classifier = Student::getCity;
Function<Student, String> mapper = Student::getName;
Collector<String, ?, List<String>> collector1 = Collectors.toList();
// Collectors의 mapping() 메소드로 Student를 이름으로 매핑하고 이름을 List에 수집하는 Collector를 얻는다.
Collector<Student, ?, List<String>> collector2 = Collectors.mapping(mapper, collector1);
Collector<Student, ?, Map<Student.City, List<String>>> collector3 =
Collectors.groupingBy(classifier, collector2);
Map<Student.City, List<String>> mapByCity = totalStream.collect(collector3);
System.out.println(mapByCity);
mapByCity = totalList.stream()
.collect(
Collectors.groupingBy(
Student::getCity,
Collectors.mapping(Student::getName, Collectors.toList())
)
);
System.out.println(mapByCity);
// groupingBy(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream)
// 위의 코드와 동일하나 TreeMap 객체를 생성해서 반환하도록 한다.
mapByCity = totalList.stream()
.collect(
Collectors.groupingBy(
Student::getCity,
TreeMap::new,
Collectors.mapping(Student::getName, Collectors.toList())
)
);
System.out.println(mapByCity);
}
}
{Seoul=[손생, 원숭이], Incheon=[깡냉, 크리스챤, 완두콩, 완두콩2]}
반응형
'프로그래밍 노트 > JAVA' 카테고리의 다른 글
[Java] LocalDate, LocalDateTime 날짜 차이 계산하기 (0) | 2020.12.22 |
---|---|
[JAVA] JVM 가상머신 메모리 구조 (0) | 2020.12.19 |
[JAVA] Stream 사용자 정의 컨테이너에 수집하기(collect()) (0) | 2020.01.07 |
[JAVA] Stream 필터링한 요소 수집(collect()) (0) | 2020.01.07 |
[JAVA] Stream 매칭(allMatch(), anyMatch(), noneMatch()) (0) | 2020.01.07 |