목차
· Collectors
· toMap
· Grouping By
· Partitioning By
· For Each
Collectors
<R, A> R collect(Collector<? super T, A, R> collector);
java.util.stream.Collectors
Collector<T, ?, List<T>> toList();
Collector<T, ?, Set<T>> toSet();
collect – 주어진 collector를 이용해 Stream안의 데이터를 합침. 일반적으로 특정 data structure로 데이터를 모을 때 사용한다. Collectors – 자주 쓰일법한 유용한 collector들을 모아놓은 util class. java.util.stream 패키지에서 제공한다.
toList – Stream 안의 데이터를 List 형태로 반환해주는 collector이다.
toSet – Stream 안의 데이터를 Set 형태로 반환해주는 collector이다.
다음은 List와 Set으로 스트림 데이터를 합치는 과정이다.
List<Integer> numberList = Stream.of(3, 5, -3, 3, 4, 5)
.collect(Collectors.toList());
System.out.println("numberList = " + numberList);
Set<Integer> numberSet = Stream.of(3, 5, -4, 4, 4, 5)
.collect(Collectors.toSet());
System.out.println("numberSet = " + numberSet);
collect로 데이터를 합칠 때 Collectors의 mapping과 reducing을 적용할 수 있다.
List<Integer> integerList = Stream.of(3, 5, -3, 3, 4, 5)
.collect(Collectors.mapping(x -> Math.abs(x), Collectors.toList()));
Set<Integer> integerSet = Stream.of(3, 5, -3, 3, 4, 5)
.collect(Collectors.mapping(x -> Math.abs(x), Collectors.toSet()));
System.out.println("integerList = " + integerList);
System.out.println("integerSet = " + integerSet);
Integer sum = Stream.of(3, 5, -3, 3, 4, 5)
.collect(Collectors.reducing(0, (x, y) -> x + y));
System.out.println("sum = " + sum);
public static <T, U, A, R> Collector<T, ?, R> mapping(
Function<? super T, ? extends U> mapper, Collector<? super U, A, R> downstream)
public static <T> Collector<T, ?, T> reducing(
T identity, BinaryOperator<T> op)
mapping – Map과 collect를 합쳐놓은 역할을 해주는 collector
reducing – reduce를 해주는 collector
toMap
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper)
Stream 안의 데이터를 map의 형태로 반환해주는 collector
keyMapper – 데이터를 map의 key로 변환하는 Function
valueMapper – 데이터를 map의 value로 변환하는 Function
다음은 toMap을 사용해 멤버 아이디를 Key로 Member를 값으로 하는 Map을 만든다.
List<Member> members = new ArrayList<>();
members.add(new Member(1, "Kim", 20));
members.add(new Member(2, "An", 40));
members.add(new Member(3, "Oh", 60));
Map<Integer, Member> memberIdMap = members.stream()
.collect(Collectors.toMap(Member::getId, Function.identity()));
Grouping By
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(
Function<? super T, ? extends K> classifier)
Stream 안의 데이터에 classifier를 적용했을 때 결괏값이 같은 값끼리 List로 모아서 Map의 형태로 반환해주는 collector.
이 때 key는 classifier의 결괏값, value는 그 결괏값을 갖는 데이터들.
처음 예시는 10으로 나눴을 때 나머지를 key로 하고 이에 해당하는 스트림 데이터 리스트를 value로 가지는 Map을 만든다.
두 번째 예시는 처음 예시의 value인 리스트를 Set으로 바꿔준다.
세 번째 예시는 처음 예시의 value인 리스트에 mapping을 적용한 이후 리스트로 변형한다.
List<Integer> numbers = Arrays.asList(13, 2, 101, 203, 304, 402, 305, 349, 2312, 203);
Map<Integer, List<Integer>> unitDigitMap = numbers.stream()
.collect(Collectors.groupingBy(number -> number % 10));
System.out.println("unitDigitMap = " + unitDigitMap);
// unitDigitMap = {1=[101], 2=[2, 402, 2312], 3=[13, 203, 203], 4=[304], 5=[305], 9=[349]}
Map<Integer, Set<Integer>> unitDigitSet = numbers.stream()
.collect(Collectors.groupingBy(number -> number % 10, Collectors.toSet()));
System.out.println("unitDigitSet = " + unitDigitSet);
// unitDigitSet = {1=[101], 2=[2, 402, 2312], 3=[203, 13], 4=[304], 5=[305], 9=[349]}
Map<Integer, List<String>> unitDigitStrMap = numbers.stream()
.collect(Collectors.groupingBy(number -> number % 10,
Collectors.mapping(number -> "unit digit is " + number, Collectors.toList())));
// unitDigitStrMap = {1=[unit digit is 101], 2=[unit digit is 2, unit digit is 402, unit digit is 2312], 3=[unit digit is 13, unit digit is 203, unit digit is 203], 4=[unit digit is 304], 5=[unit digit is 305], 9=[unit digit is 349]}
Partitioning By
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(
Predicate<? super T> predicate)
public static <T, D, A> Collector<T, ?, Map<Boolean, D>> partitioningBy(
Predicate<? super T> predicate, Collector<? super T, A, D> downstream
GroupingBy와 유사하지만 Function 대신 Predicate을 받아 true와 false 두 key가 존재하는 map을 반환하는 collector
마찬가지로 downstream collector를 넘겨 List 이외의 형태로 map의 value를 만드는 것 역시 가능
List<Integer> numbers = Arrays.asList(13, 2, 101, 203, 304, 402, 305, 349, 2312, 203);
// 짝수인 그룹, 홀수인 그룹으로 나누기
Map<Boolean, List<Integer>> numberPartitions = numbers.stream()
.collect(Collectors.partitioningBy(number->number %2 ==0 ));
System.out.println("numberPartitions.get(true) = " + numberPartitions.get(true));
System.out.println("numberPartitions.get(false) = " + numberPartitions.get(false));
// numberPartitions.get(true) = [2, 304, 402, 2312]
// numberPartitions.get(false) = [13, 101, 203, 305, 349, 203]
For Each
void forEach(Consumer<? super T> action);
제공된 action을 Stream의 각 데이터에 적용해주는 종결 처리 메서드
Java의 iterable 인터페이스에도 forEach가 있기 때문에 Stream의 중간 처리가 필요 없다면 iterable collection(Set, List 등)에서 바로 쓰는 것도 가능
List<Integer> numbers = Arrays.asList(3, 5, 2, 1);
numbers.stream().forEach(number-> System.out.println("number = " + number));
'Language > Java' 카테고리의 다른 글
Java 스트림 (Stream) 사용법 및 정리 2/3 (Reduce, Max, Min ..) (0) | 2022.10.10 |
---|---|
Java 스트림 (Stream) 사용법 및 정리 1/3 (Map, Filter, FlatMap ..) (0) | 2022.10.09 |
Java 메서드 참조란? (0) | 2022.10.09 |
Java 8 함수형 인터페이스 이해하기 (0) | 2022.10.08 |
Java 람다 표현식과 Function Interface (0) | 2022.10.08 |