korjun1993 / cs-book-study

책을 읽고 토론하며 컴퓨터과학을 공부하는 공간
0 stars 1 forks source link

스트림의 최종 연산 #44

Open korjun1993 opened 1 year ago

korjun1993 commented 1 year ago

스트림의 최종 연산

// 병렬 스트림인 경우에는 findFirst 대신 findAny를 사용해야 한다. stuStream.parallel().filter(s->s.getTotalScore() <= 100).findAny();


- 통계
IntStream과 같은 기본형 스트림에는 스트림의 요소들에 대한 통계 정보를 얻을 수 있는 메서드들이 있다. 그러나 기본형 스트림이 아닌 경우에는 통계와 관련된 메서드들이 아래의 3개뿐이다.
```java
long count();
Optional<T> max(Comparator<? super T> comparator)
Optional<T> min(Comparator<? super T> comparator)

// 예시 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()

// for문으로 sum()을 표현하면 다음과 같다. int a = identity // 초기값을 a에 저장한다. for (int b : stream) { a = a + b; // 모든 요소의 값을 a에 누적한다. }

// 즉, 일반화하면 다음과 같다. T reduce(T identity, BinaryOperator accumulator) { T a = identity; for (T b : stream) { a = accumulator.apply(a, b); } return a; }


- collector
   - collect()가 스트림의 요소를 수집한다. 이 때 어떻게 수집할 것인가에 대한 방법을 정의한 것이 컬렉터(collector)이다.
   - 컬렉터는 Collector 인터페이스를 구현한 것으로, 직접 구현할 수도 있고 미리 작성된 것을 사용할 수도 있다.
   - Collectors 클래스는 미리 작성된 다양한 종류의 컬렉터를 반환하는 static 메서드를 가지고 있다.

- 스트림 → 컬렉션
```java
// Collectors 클래스의 toList()와 같은 메서드를 사용하면된다.
List<String> names = stuStream.map(Student::getName).collect(Collectors.toList());

// Map으로 바꾸려면 어떤 필드를 키, 값으로 사용할지 지정해줘야 한다.
Map<String, Person> map = personStream.collect(Collectors.toMap(p -> p.getRegId(), p->p));

// Student의 toString()으로 결합 String studentInfo = stuStream.collect(Collectors.joining(","));


- 분할
   - 스트림의 지정된 조건에 일치하는 그룹과 일치하지 않는 그룹으로 분할한다. 
```java
Collector partitioningBy(Predicate predicate)
Collector partitioningBy(Predicate predicate, Collector downstream)

// 학생들을 성별로 분할
Map<Boolean, List<Student>> stuBySex = stuStream.collect(Collectors.partitioningBy(Student::isMale));

List<Student> maleStudent = stuBySex.get(true);
List<Student> femaleStudent = stuBySex.get(false);

// 성별 학생들의 수
Map<Boolean, Long>> stuNumBySex = stuStream.collect(Collectors.partitioningBy(Student::isMale, Collectors.counting()));

long maleNum = stuNumBySex.get(true);
long femaleNum = stuNumBySex.get(false);

// 성별로 성적이 150점이 아래인 학생
Map<Boolean, Map<Boolean, List<Student>>> failedStuBySex = Stream.of(stuArr)
            .collect(Collectors.partitioningBy(Student::isMale, Collectors.partitioningBy(s -> s.getScore() <= 100)));

// 예시 // 1. 그룹화(반별) Map<Integer, List> stuByBan = Stream.of(stuArr).collect(Collectors.groupingBy(Student2::getBan));

// 2. 그룹화(성적별) Map<Student2.Level, List> stuByLevel = Stream.of(stuArr).collect(Collectors.groupingBy(s -> { if (s.getScore() >= 200) { return Student2.Level.HIGH; } else if (s.getScore() >= 100) { return Student2.Level.MID; } else { return Student2.Level.LOW; } }));

// 3. 그룹화 + 통계(성적별 학생수) Map<Student2.Level, Long> stuCntByLevel = Stream.of(stuArr).collect(Collectors.groupingBy(s -> { if (s.getScore() >= 200) { return Student2.Level.HIGH; } else if (s.getScore() >= 100) { return Student2.Level.MID; } else { return Student2.Level.LOW; } }, Collectors.counting()));