Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- SQL
- 코테
- 구현
- Stack
- 파이썬
- Math
- 자바
- greedy
- hash table
- 코딩테스트
- simulation
- dynamic programming
- Counting
- implement
- string
- Data Structure
- Matrix
- geometry
- java
- array
- Binary Tree
- bit manipulation
- Tree
- Binary Search
- sorting
- two pointers
- Number Theory
- database
- Class
- Method
Archives
- Today
- Total
코린이의 소소한 공부노트
스트림의 그룹화와 분할 본문
[collect()]
1. Collector 인터페이스를 매개변수로 하는 스트림의 최종연산
2. reduce()는 전체에 대해 리듀싱, collect()는 그룹별로 리듀싱
// 스트림의 요소를 수집. 요소를 그룹화/분할한 결과를 컬렉션에 담아서 반환. 최종 연산의 핵심2
R collect(Collector<T,A,R> collector) // Collector를 구현한 클래스의 객체를 매개변수로
R collect(Supplier<R> supplier, BiConsumer<R,T> accumulator, BiConsumer<R,R> combiner) // 잘 안씀
[Collector]
1. 수집(collect)에 필요한 메서드를 정의해 놓은 인터페이스
2. collect()의 매개변수를 5개를 쓰려니 너무 많아서 인터페이스로 묶어둔 것이다.
3. reduce()는 identity, accumulator가 핵심이었다면, Collector는 supplier(), accumulator()가 핵심이다.
public interface Collector<T, A, R> { // T(요소)를 A에 누적한 다음, 결과를 R로 변환해서 반환
Supplier<A> supplier(); // StringBuilder::new 누적할 곳
BiConsumer<A, T> accumulator(); // (sb, s) -> sb.append(s) 누적방법
BinaryOperator<A> combiner(); // (sb1, sb2) -> sb1.append(sb2) 결합방법(병렬)
Function<A, R> finisher(); // sb -> sb.toString() 최종변환
Set<Characteristics> characteristics(); // 컬렉터의 특성이 담긴 Set을 반환
...
}
[Collectors]
1. Collector를 구현한 클래스
2. 다양한 기능을 제공한다.
3. Collector는 인터페이스이기 때문에 직접 구현해서 사용해야 하지만, Collectors 클래스에 대부분 있기 때문에 가져다 쓰기만 하면 된다.
변환 - mapping(), toList(), toSet(), toMap(), toCollection(), ...
통계 - counting(), summingInt(), averagingInt(), maxBy(), minBy(), summarizingInt(), ...
문자열 결합 - joining()
리듀싱 - reducing()
그룹화와 분할 - groupingBy(), partitioningBy(), collectingAndThen()
[Collectors의 메서드]
1. 스트림을 컬렉션으로 변환 - toList( ), toSet( ), toMap( ), toCollection( )
List<String> names = stuStream.map(Student::getName) // Stream<Student>→Stream<String>
.collect(Collectors.toList()); // Stream<String>→List<String>
ArrayList<String> list = names.stream()
.collect(Collectors.toCollection(ArrayList::new)); // Stream<String>→ArrayList<String>
Map<String,Person> map = personStream
.collect(Collectors.toMap(p->p.getRegId(), p->p)); // Stream<Person>→Map<String,Person>
2. 스트림의 그룹별로 통계정보 제공 – counting( ), summingInt( ), maxBy( ), minBy( ), …
long count = stuStream.count();
long count = stuStream.collect(counting()); // Collectors.counting() 스태틱 임포트
long totalScore = stuStream.mapToInt(Student::getTotalScore).sum(); // IntStream의 sum()
long totalScore = stuStream.collect(summingInt(Student::getTotalScore)); // 위 코드와 같음
OptionalInt topScore = studentStream.mapToInt(Student::getTotalScore).max();
Optional<Student> topStudent = stuStream
.max(Comparator.comparingInt(Student::getTotalScore));
Optional<Student> topStudent = stuStream
.collect(maxBy(Comparator.comparingInt(Student::getTotalScore)));
3. 스트림을 그룹별로 리듀싱 – reducing( )
Collector reducing(BinaryOperator<T> op)
Collector reducing(T identity, BinaryOperator<T> op) // 초기값, 누적작업
Collector reducing(U identity, Function<T,U> mapper, BinaryOperator<U> op)
// map+reduce. 초기값, 변환작업, 누적작업
IntStream intStream = new Random().ints(1,46).distinct().limit(6);
OptionalInt max = intStream.reduce(Integer::max);
Optional<Integer> max = intStream.boxed().collect(reducing(Integer::max));
long sum = intStream.reduce(0, (a,b) -> a + b);
long sum = intStream.boxed().collect(reducing(0, (a,b)-> a + b));
int grandTotal = stuStream.map(Student::getTotalScore).reduce(0, Integer::sum);
int grandTotal = stuStream.collect(reducing(0, Student::getTotalScore, Integer::sum));
4. 문자열 스트림의 요소를 모두 연결 – joining( )
String studentNames = stuStream.map(Student::getName)
.collect(joining());// Collectors.joining() 스태틱 임포트
String studentNames = stuStream.map(Student::getName).collect(joining(",")); // 구분자
String studentNames = stuStream.map(Student::getName).collect(joining(",", "[", "]"));
String studentInfo = stuStream.collect(joining(",")); // Student의 toString()으로 결합
5. 스트림의 요소를 그룹화(2분할) – partitioningBy( )
Collector partitioningBy(Predicate predicate)
Collector partitioningBy(Predicate predicate, Collector downstream)
// 예시
Map<Boolean, List<Student>> stuBySex = stuStream
.collect(partitioningBy(Student::isMale)); // 학생들을 성별로 분할
List<Student> maleStudent = stuBySex.get(true); // Map에서 남학생 목록을 얻는다.
List<Student> femaleStudent = stuBySex.get(false); // Map에서 여학생 목록을 얻는다.
Map<Boolean, Long> stuNumBySex = stuStream
.collect(partitioningBy(Student::isMale, counting())); // 분할 + 통계
System.out.println("남학생 수 :"+ stuNumBySex.get(true)); // 남학생 수 :8
System.out.println("여학생 수 :"+ stuNumBySex.get(false)); // 여학생 수 :10
Map<Boolean, Optional<Student>> topScoreBySex = stuStream // 분할 + 통계
.collect(partitioningBy(Student::isMale, maxBy(comparingInt(Student::getScore))));
System.out.println("남학생 1등 :"+ topScoreBySex.get(true)); // 남학생 1등 :Optional[[나자바,남, 1, 1,300]]
System.out.println("여학생 1등 :"+ topScoreBySex.get(false)); //여학생 1등 :Optional[[김지미,여, 1, 1,250]]
Map<Boolean, Map<Boolean, List<Student>>> failedStuBySex = stuStream // 다중 분할
.collect(partitioningBy(Student::isMale, // 1. 성별로 분할(남/녀)
partitioningBy(s -> s.getScore() < 150))); // 2. 성적으로 분할(불합격/합격)
List<Student> failedMaleStu = failedStuBySex.get(true).get(true);
List<Student> failedFemaleStu = failedStuBySex.get(false).get(true);
List<Student> passedMaleStu = failedStuBySex.get(true).get(false);
List<Student> passedFemaleStu = failedStuBySex.get(false).get(false);
6. 스트림의 요소를 그룹화(n분할) – groupingBy( )
Collector groupingBy(Function classifier)
Collector groupingBy(Function classifier, Collector downstream)
Collector groupingBy(Function classifier, Supplier mapFactory, Collector downstream)
// 예시
Map<Integer, List<Student>> stuByBan = stuStream // 학생을 반별로 그룹화
.collect(groupingBy(Student::getBan, toList())); // toList() 생략가능
Map<Integer, Map<Integer, List<Student>>> stuByHakAndBan = stuStream // 다중 그룹화
.collect(groupingBy(Student::getHak, // 1. 학년별 그룹화
groupingBy(Student::getBan) // 2. 반별 그룹화
));
Map<Integer, Map<Integer, Set<Student.Level>>> stuByHakAndBan = stuStream
.collect(
groupingBy(Student::getHak, groupingBy(Student::getBan, // 다중 그룹화(학년별, 반별)
mapping(s-> { // 성적등급(Level)으로 변환. List<Student> → Set<Student.Level>
if (s.getScore() >= 200) return Student.Level.HIGH;
else if(s.getScore() >= 100) return Student.Level.MID;
else return Student.Level.LOW;
} , toSet()) // mapping() // enum Level { HIGH, MID, LOW }
)) // groupingBy()
); // collect()
[쿠키글] 스트림의 변환
// 스트림 -> 기본형 스트림
mapToInt(ToIntFunction<T> maaper) // Stream<T> -> IntStream
mapToLong(ToLongFunction<T> maaper) // Stream<T> -> LongStream
mapToDouble(ToDoubleFunction<T> maaper) // Stream<T> -> DoubleStream
// 기본형 스트림 -> 스트림
boxed() // Int/Long/DoubleStream -> Stream<Integer>/<Long>/<Double>
mapToObj(DoubleFunction<U> maaper) // Int/Long/DoubleStream -> Stream<U>
// 기본형 스트림 -> 기본형 스트림
asLongStream() // Int/DoubleStream -> LongStream
asDoubleStream() // Int/LongStream -> DoubleStream
// 스트림 -> 부분 스트림
skip(long n) // Stream<T> -> Stream<T>
limit(long maxSize) // IntStream -> IntStream
// 두 개의 스트림 -> 스트림
concat(Stream<T> a, Stream<T> b) // Stream<T>, Stream<T> -> Stream<T>
concat(IntStream a, IntStream b) // IntStream, IntStream -> IntStream
concat(LongStream a, LongStream b) // LongStream, LongStream -> LongStream
concat(DoubleStream a, DoubleStream b) // DoubleStream, DoubleStream -> DoubleStream
// 스트림의 스트림 -> 스트림
flatMap(Function mapper) // Stream<Stream<T>> -> Stream<T>
flatMapToInt(Function mapper) // Stream<IntStream> -> IntStream
flatMapToLong(Function mapper) // Stream<LongStream> -> LongStream
flatMapToDouble(Function mapper) // Stream<DoubleStream> -> DoubleStream
// 스트림 <-> 병렬스트림
// Stream<T>/Int/Long/DoubleStream <-> Stream<T>/Int/Long/DoubleStream
parallel() // 스트림 -> 병렬스트림
sequential() // 병렬스트림 -> 스트림
// 스트림 -> 컬렉션
collect(Collectors.toCollection(Supplier factory))
// Stream<T>/Int/Long/DoubleStream -> Collection<T>
collect(Collectors.toList()) // Stream<T>/Int/Long/DoubleStream -> List<T>
collect(Collectors.toSet()) // Stream<T>/Int/Long/DoubleStream -> Set<T>
// 컬렉션 -> 스트림
stream() // Collection<T>/List<T>/Set<T> -> Stream<T>
// 스트림 -> Map
// Stream<T>/Int/Long/DoubleStream -> Map<K,V>
collect(Collectors.toMap(Function Key, Function value))
collect(Collectors.toMap(Function, Function, BinaryOperator))
collect(Collectors.toMap(Function, Function, BinaryOperator merge, Supplier mapSupplier))
// 스트림 -> 배열
toArray() // Stream<T> -> Object[]
toArray(IntFunction<A[]> generator) // T[]
toArray() // Int/Long/DoubleStream -> int[]/long[]/double[]
'Java' 카테고리의 다른 글
스트림의 최종 연산 (0) | 2023.02.21 |
---|---|
Optional 클래스 (0) | 2023.02.07 |
스트림의 중간 연산 (0) | 2023.02.07 |
스트림 생성하기 (0) | 2023.02.01 |
스트림의 정의와 특징 (0) | 2023.01.30 |