세 줄 요약
- 최종 처리 기능을 담당하는 메소드를 체이닝 패턴 마지막에 위치시켜 내부 반복을 종료한다.
- 집계 처리 메소드 중 Optional 타입을 리턴하는 메소드는 get() 메소드를 통해 그 값을 얻는다.
- collect() 메소드를 사용해서 중간 처리를 거친 요소를 컬렉션에 담을 수 있다.
루핑
스트림에서 요소를 하나씩 반복해서 가져와 처리하는 것을 말합니다.
매개타입은 함수형 인터페이스인 Consumer이며, 해당 인터페이스에는 매개값을 처리하는 accept() 메소드가 있습니다.
forEach( ) / peek( )
둘 다 요소를 하나씩 반복해서 가져오는 기능을 수행합니다.
다만, peek() 메소드는 최종 처리 기능이 아니므로 스트림 메소드 체이닝 패턴에서 마지막에 위치할 수 없습니다.
아래 예제에서는 정수 스트림에서 짝수만 출력합니다.
매칭
요소들이 특정 조건에 부합하는지 여부를 조사하는 최종 처리 기능입니다.
filter()와 마찬가지로 Predicate가 매개값으로 true 혹은 false를 리턴해서 넘겨줍니다.
allMatch( )
모든 요소가 만족하는지 여부 조사
anyMatch( )
최소한 하나의 요소가 만족하는지 여부 조사
noneMatch( )
모든 요소가 만족하지 않는지 여부 조사
다음 예제에서는 정수 스트림의 모든 요소가 2의 배수인지, 하나라도 3의 배수가 존재하는지, 3의 배수가 존재하지 않는지 조사합니다.
기본 집계
스트림에서 제공하는 기본 집계 메소드는 다음과 같습니다.
리턴 타입이 Optional인 경우 get() / getAsInt() / getAsLong() / getAsDouble() 메소드를 통해 최종값을 얻습니다.
int[ ] arr = {1, 2, 3, 4, 5}
findFirst( )
첫 번째 요소(Optional)
// 3의 배수 첫 번째 요소 구하기
int first = Arrays.stream(arr)
.filter(n -> n % 3 == 0)
.findFirst
.getAsInt();
// first = 3
max( ) / max(Comparator<T>)
최대 요소(Optional)
// 2의 배수 최대값 구하기
int max = Arrays.stream(arr)
.filter(n -> n % 2 == 0)
.max()
.getAsInt()
// max = 4
min( ) / min(Comparator<T>)
최소 요소(Optional)
// 2의 배수 최소값 구하기
int min = Arrays.stream(arr)
.filter(n -> n % 2 == 0)
.min()
.getAsInt()
// min = 2
average( )
요소 평균(Optional)
// 2의 배수 평균 구하기
double avg = Arrays.stream(arr)
.filter(n -> n % 2 == 0)
.average()
.getAsDouble();
// avg = 3.0
count( )
요소 개수(long)
// 2의 배수 개수 구하기
long count = Arrays.stream(arr)
.filter(n -> n % 2 == 0)
.count();
// count = 2
sum( )
요소 총합(int / long / double)
// 2의 배수 합 구하기
long sum = Arrays.stream(arr)
.filter(n -> n % 2 == 0)
.sum();
// sum = 6
커스텀 집계
기본 집계 메소드 외에도 다양한 집계 결과를 만들 수 있는 reduce() 메소드가 있습니다.
reduce( )
매개값으로 가지는 함수형 인터페이스 BinaryOperator는 두 개의 매개값을 받아 하나의 값을 리턴하는 apply() 메소드를 가지고 있으며, 누적 집계를 실행합니다.
스트림에 요소가 없는 경우 NoSuchElementException을 발생시키지만, 초기 값(identity)을 제공해 예방할 수 있습니다.
int[] arr = {3, 4, 5};
int result1 = Arrays.stream(arr)
.reduce(0, (a, b) -> a + b);
// result1 = 12 (만약 요소가 없다면 0 리턴)
int result2 = Arrays.stream(arr)
.reduce(2, (a, b) -> a * b);
// result2 = 120 (2부터 누적 곱 실햄)
수집
collect() 메소드를 통해 중간 처리 과정이 끝난 스트림의 요소를 컬렉션에 담을 수 있습니다.
toList( )
객체 T를 List에 저장
- Java16 이전 : stream().collect(Collectors.toList());
- Java16 이후 : stream().toList();
List<String> maleList = list.stream()
.filter(s -> s.sex.equals("남"))
.map(s -> s.name)
.toList();
// maleList = [홍길동, 김자바]
toSet( )
객체 T를 Set에 저장
Set<String> set = list.stream()
.map(s -> s.name)
.collect(Collectors.toSet());
// set = [김자바, 홍길동, 아이유]
toMap( )
객체 T를 key : value 형태로 Map에 저장
Map<String, Integer> map = list.stream()
.collect(
Collectors.toMap(
s -> s.name, // key
s -> s.score // value
)
);
// map = {김자바=95, 홍길동=92, 아이유=88}
그룹핑
collect() 메소드는 요소의 수집 외에도 컬렉션의 요소들을 그룹핑해서 Map객체를 생성하는 기능도 제공합니다.
groupingBy( )
객체 T를 K로 매핑 후 K(key) : List<T>(value)의 Map 컬렉션을 생성
// 성별을 key로 갖고 Student 객체를 value로 갖는 map 생성
Map<String, List<Student>> map = list.stream()
.collect(
Collectors.groupingBy(s -> s.sex)
);
List<Student> maleList = map.get("남"); // 남학생 리스트
List<Student> femaleList = map.get("여"); // 여학생 리스트
groupingBy() 메소드는 매핑 및 집계 처리를 할 수 있도록 두 번째 매개값인 Collector를 가질 수 있습니다.
두 번째 매개값으로 사용할 Collector는 다음과 같은 Collectors의 정적 메소드들을 사용해 얻습니다.
mapping() : 매핑
averagingDouble() : 평균값
counting() : 요소의 개수
maxBy() : 최대값
minBy() : 최소값
reducing() : 커스텀 집계값
// 학생들을 성별로 그룹핑하고 각각의 평균 점수를 구해서 map 생성
Map<String, Double> map = list.stream()
.collect(
Collectors.groupingBy(
s -> s.sex, // 첫 번째 매개값
Collectors.averagingDouble(s -> s.score) // 두 번째 매개값
)
);
// map = {남=93.5, 여=88.0}
'Spring-Java > Java' 카테고리의 다른 글
super, super() (0) | 2024.04.24 |
---|---|
Optional 클래스 (2) | 2024.04.05 |
스트림(Stream)_중간 처리 기능 (1) | 2024.04.04 |
익명 객체와 람다식(lambda) (0) | 2024.04.03 |
Day10_class 예제 (0) | 2023.08.28 |