반응형

스트림의 그룹화와 분할

  • partitioningBy()는 스트림을 2분할한다.

Collectors에 있는paritioningBy() 메서드는 스트림을 2분할 한다.

이렇게 두가지 오버로드 된 메서드가 있다. 

 

  • groupingBy()는 스트림을 n분할한다.

Collectors에 있는 groupBy() 메서드는 스트림을 n분할 한다.

 

collect()는 partitioningBy()나 groupingBy()를 같이 사용해서 스트림을 분할해서 나눠놓고,
거기에 대한 통계정보라던가, 이런 것들을 적용할 수 있다. 
이것이 바로 collect()의 장점이다.

 

스트림의 분할 - partitioningBy()

  • 스트림의 요소를 2분할

stuStream을 .collect를 하고, partitioningBy()를 이용해서 성별로 나눈 것이다ㅏ.
그러면, 남자와 여자 두가지로 나누어 질 것이다.  (2분할)
이럴 때 사용하는 것이  partitioningBy()이다.

groupingBy()를 사용해도 되지만, 굳이 2분할 할 것을 groupingBy()를 사용할 필요는 없다.

위 코드처럼 학생들을 성별로 분할하기 위해서 .collect(partitioningBy(Student::isMale))을 사용하면 true, false가 2분할로 반환되는데, stuBySex.get(true)를 하면, key가 true이고 value가 List<Student>인 Map이 반환된다.
stuBySex.get(false)를 하면, key가 false이고 value가 List<Student>인 Map이 반환된다.

 

.collect(partitioningBy(Student::isMale, counting()))이렇게 그리고 성별로 나눈 다음에, counting()도 가능하다. Collectors.counting()인데 Collectors가 생략된 것이다.
반환값은 Map<Boolean, Long> 이다.
그래서 stuNumBySex.get(true) 를 하면 남학생수를 얻을 수 있고,
stuNumBySex.get(false)를 하면 여학생수를 얻을 수 있다.

 

이번에는 .collect(partitioningBy(Student : isMale, maxBy(comparingInt(Student :: getScore)))이렇게하면,
학생을 성별로 나누고, 최대값을 구한다. 최댓값을 구하는 기준은 getScore 즉, 성적이다. 성별을 나누고 각각 성적이 가장 좋은 학생을 구하는 것이다.
그 결과는 Optional로 되어있다.
get(true)를 하면, 남학생 중에 1등, get(false)하면 여학생 중에 1등이 나오게 된다.

각 분할한 그룹별로 최댓값을 구한 것이라고 볼 수 있다.

 

그리고 patition을 여러번 나눌 수 있다. 이것을 다중분할이라고 한다.

.collect(partitioningBy(Student :: isMale, partitioningBy(s -> s.getScore() < 150)))
위의 코드는 학생을 남자 여자 두그룹으로 나누고 또 합격 불합격으로 그룹을 둘로나눈 것이다.
남자 여자는 성별로 나누고, 합격 불합격은 성적이 150미만이면 불합격이다.

failedStuBySex.get(true).get(true)는 남자 불합격 을 구하는 것이고,
failedStuBySex.get(false).get(false)는 여자 불합격을 구하는 것이다.

 

 

 

스트림의 그룹화 - groupingBy()

  • 스트림의 요소를 n분할하여 그룹화

이러한 메서드 들이 있다.

 

.collect(groupingBy(Student::getBan, toList()))는 반을 기준으로 나누고, 반에 따라서 리스트에 담아서 결과를 반환하는 것이다.
그래서 반환 Map이 <Integer, List<Student>이렇게 되어있다.
코드에서 toList()는 디폴트 값이기 때문에 생략이 가능하다.

사실 partitioningBy와 똑같다고 보면된다. 2분할이냐, n분할 이냐의 차이이다.

 

이번에는 다중그룹화다. 학년으로 나눈다음에 도 반별로 나눴다.
.collect(groupingBy(Student::getHak, groupingBy(Student::getBan)));
key가 1학년이라면, value에는 key는 반, value는 학생들 List<Student>가 들어갈 것이다. 이러한 구조를 가지게 된다.

 

우리가 특별한 기준으로 좀더 복잡하게 나누려면, mapping()을 사용하면 된다.
성적을 조건별로 나눈 것이다. 200점 이상인 사람인 HIGH, 100점 이상인 사람인 MID, 나머지는 LOW로 나누는 것이다.
학년별로 나누고 반별로 나눈다음, 성적별로 N분할 한 것이다.

그래서 반환타입을 보면,
Map<Integer, Map<Integer, Set<Student.Level>>>이다. Map안에 또 Map이 있다.

 

 

스트림의 변환

 

반응형

'JAVA' 카테고리의 다른 글

[JAVA] JVM 동작원리 및 기본개념(JVM Internal)  (0) 2022.12.07
collect()와 Collectors  (0) 2022.11.30
스트림의 최종연산  (0) 2022.11.25
Optional<T>  (0) 2022.11.22
스트림의 중간연산(2)  (0) 2022.11.19