본문 바로가기

Java

스트림 최종연산

출처 - Java의 정석 기초편 (남궁 성)

 

 

1. 스트림 최종연산

- 핵심: reduce(), collect()

 

void forEach(Consumer<? super T> action)
void forEachOrdered(Consume<? super T> action) // 병렬 스트림 순서 유지
long count() // 스트림 요소 개수
Optional<T> max(Comparator<? super T> comparator)
Optional<T> min(Comparator<? super T> comparator)
Optional<T> findFirst() // 직렬 첫 번째 요소
Optional<T> findAny() // 병렬 아무거나 하나
boolean allMatch(Predicate<T> p) // 모두 만족
boolean anyMach(Predicate<T> p) // 하나라도 만족
boolean nomeMach(Predicate<T> p) // 모두 만족하지 않는지
Object[] toArray()
A[] toArray(IntFunction<A[]> generator)
Optional<T> reduce(BinaryOperator<T> accumulator) // 요소 하나씩 줄여가며 계산
R collect(Collector<T,A,R> collector) // 그룹 작업

 

 

2. forEach()

- 스트림 모든 요소에 지정된 작업 수행

- forEachOrdered(): 병렬시 순서 유지

 

IntStream.range(1, 10).parellel().forEach(System.out::print); // 524931678
IntStream.range(1, 10).parellel().forEachOrderedd(System.out::print); // 123456789

 

 

3. 조건검사

- 조건검사(매개변수 Predicate), 반환타입 boolean): allMatch(), anyMatch(), noneMatch()

- 조건 일치하는 요소 찾기: findFirst(), findAny()

 

boolean noFailed = stuStream.anyMatch(s->s.getTotalScore()<=100)

Optional<Student> result = stuStream.filter(s->s.getTotalScore()<=100).findFirst(); // 직렬
Optional<Student> result = parallelStream.filter(s->s.getTotalScore()<=100).findAny(); // 병렬

 

 

4. reduce()

- 초기값(identity)과 연산(Binary Operator)으로 스트림 요소를 하나씩 줄여가며 누적연산(accumulate) 수행

- 매개변수 타입: BinaryOperator<T>

- 반환타입: 초기값 있으면 identity 반환, 없으면 Optional<T> 반환

- 활용: count(). max(), min(). collect()

 

Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce(T identity, BinaryOperator<T> accumulator)

int count = intStream.reduce(0, (a,b) -> a + 1); // count()
int sum = intStream.reduce(0, (a,b) -> a + b); // sum()
int max = intStream.reduce(Integer.MIN_VALUE, (a,b) -> a>b ? a:b) // max()
int min = intStream.reduce(Integer.MAX_VALUE, (a,b) -> a>b ? a:b) // min()

 

 

5. collect(), Collector, Collectors

- collect(): Collector를 매개변수로 하는 스트림의 최종 연산

- Collector: 수집(collect)에 필요한 메서드를 정의해둔 인터페이스

- Collectors: 다양한 기능의 Collector를 구현체  제공하는 클래스

 

Object collect(Collector collector)

 

 

6. Collectors 클래스

- 변환: mapping(), toList(), toSet(), toMap(), toCollection()

- 통계: countiong(), summingInt(), averagingInt(), maxBy(), minBy(), summarizingInt()

- 문자열 결합: joining()

- 리듀싱: reducing()

- 그룹화와 분할: groupingBy(), partitioningBy(), collectingAndThen()

 

 

7. 스트림→컬렉션, 배열

- 스트림→컬렉션: collect()메서드→toList(). toSet(), toMap(), toCollection()

- 스트림→배열: toArray()메서드

 

List<String> names = stuStream.map(Student::getName).collect(Collectors.toList());
ArrayList<String> list = names.stream().collect(Collectors.toCollection(ArrayList::new));
Map<String,Person> map = personStream.collect(Collectors.toMap(p->p.getRegId(), p->p));

Student[] stuNames = studentStream.toArray(Student[]::bew); // ok
Object[] stuNames = studentStream.toArray(); // 매개변수 없는 것 Object[] 반환

 

 

8. 스트림 통계

- 전체: count(), sum(), max(), min()

- 그룹별: counting(), summingInt(), maxBy(), minBy()

 

import static java.util.stream.collectors.*;

long count = stuStream.count(); // 전체 카운트
long count = stustream.collect(counting()); // 그룹별 카운트 Collectors.counting()

long totalScore = stuStream.mapToInt(Student::getTotalScore).sum();
long totalScore = stuStream.collect(summingInt(Student::getTotalScore));

Optional<Student> topStudent = stuStream.max(Comparator.comparingInt(Student::getTotalScore));
Optional<Student> topStudent = stuStream.collect(maxBy(Comparator.comparingInt(Student::getTotalScore)));

 

 

9. 스트림 리듀싱

- 전체: reduce()

- 그룹별: reducing()

 

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)); // map() + reduce()

 

 

10. 스트림→문자열로 결합

- 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(",","[","]"));

 

 

11. 스트림 분할

- Collectors.partitioningBy()

- 스트림 2분할

- 다중 분할

 

Map<Boolean, List<Student>> stuBySex = stuStream.collect(partitioningBy(Student::isMale)); // 성별로 2분할
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("남학생 수 :" + stuMumBySex.get(true));
System.out.println("여학생 수 :" + stuNumBySex.get(false));

Map<Boolean, Map<Boolean, List<Student>>> failedStuBySex = stuStream
    .collect(
        partitioningBy(Student::isMale, // 성별 분할
            partitioningBy(s -> s.getScore() < 150) // 성적 분할
        )
    );
List<Student> failedMaleStu = failedStuBySex.get(true).get(true); // 남자 불합격
List<Student> failedMaleStu = failedStuBySex.get(false).get(true); // 여자 불합격

 

 

12. 스트림 그룹화

- Collectors.groupingBy()

- 스트림 n분할

- 다중 그룹화

 

Map<Integer, List<Student>> stuByBan = stustream
    .collect(groupingBy(Student::getBan, toList())); // toList() 생략가능

Map<Integer, HashSet<Student>> stuByHak = stuStream
    .collect(groupingBy(Student::getHak, toCollection(HashSet::new)));
    
Map<Integer, Map<Integer, List<Student>>> stuByHakAndBan = stuStream
    .collect(groupingBy(Student::getHak, // 학년별 그룹화
             groupingBy(Student::getBan) // 반별 그룹화
    ));

 

 

 

'Java' 카테고리의 다른 글

Optional<T>객체  (0) 2022.12.14
스트림 중간연산  (0) 2022.12.14
스트림(Stream)  (0) 2022.12.09
람다, 함수형 인터페이스, 메서드 참조  (0) 2022.12.08
쓰레드 메서드  (0) 2022.11.19