1. 요소 기본 집계 (Aggregation)
집계(Aggregation)는 스트림의 요소들을 하나의 값으로 축소하는 기능을 의미하며, 이는 최종 처리 기능에 속한다.
즉, 집계 메소드들은 스트림 연산의 끝에서 실행된다.
스트림 API에서 제공하는 기본 집계 함수들은 다음과 같다:
🔹 기본 집계 메소드:
메소드 | 설명 |
count() | 요소 개수를 반환 (long) |
findFirst() | 첫 번째 요소 반환 (Optional) |
max(Comparator<T>) | 최대값 반환 (Optional) |
min(Comparator<T>) | 최소값 반환 (Optional) |
average() | 평균값 반환 (OptionalDouble) |
sum() | 합 반환 (int, long, double) |
📌 반환값의 특징
- count(), sum() 등의 일부 메소드는 기본 데이터 타입(int, long, double)을 반환한다.
- max(), min(), average() 등의 메소드는 Optional<T> 형태로 값을 반환한다. 이는 집계 대상 요소가 없을 경우 예외를 방지하기 위해 사용된다.
📝 예제 코드
int[] numbers = {2, 4, 6};
IntStream intStream = Arrays.stream(numbers);
// 요소 개수
long count = intStream.count();
// 요소 합
int sum = Arrays.stream(numbers)
.sum();
// 요소 평균
OptionalDouble average = Arrays.stream(numbers)
.average();
double avgValue = average.orElse(0.0); // 값이 없을 경우 기본값 0.0 반환
// 최대값
OptionalInt max = Arrays.stream(numbers)
.max();
int maxValue = max.orElseThrow(); // 값이 없으면 예외 발생
17.11 요소 커스텀 집계 (Custom Aggregation)
자바의 기본 집계 메소드(sum(), average()) 외에도 사용자가 직접 집계 기능을 구현할 수 있도록 제공되는 메소드가 reduce()이다.
🔹 reduce() 메소드
스트림의 요소들을 하나의 값으로 축소(리덕션)하기 위해 사용된다.
- accumulator: 두 개의 요소를 받아 하나로 줄이는 함수 (람다식으로 구현)
- identity: 초기값 (집계 대상이 없을 때 기본값으로 사용)
Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce(T identity, BinaryOperator<T> accumulator)
📌 reduce()를 사용한 합계 계산 예제
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 요소들의 합 구하기
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("합계: " + sum); // 출력: 15
// 요소들의 곱 구하기
int product = numbers.stream()
.reduce(1, (a, b) -> a * b);
System.out.println("곱셈 결과: " + product); // 출력: 120
// 최소값 구하기
Optional<Integer> min = numbers.stream()
.reduce(Integer::min);
System.out.println("최소값: " + min.orElse(-1)); // 출력: 1
💡 reduce()의 동작 방식
- 초기값(Identity)을 먼저 설정 (없으면 Optional로 반환)
- 첫 번째와 두 번째 요소를 연산하여 결과를 저장
- 결과와 세 번째 요소를 연산하여 새로운 결과를 저장
- 반복적으로 진행하여 최종 결과 도출
2. 요소 수집 (Collecting)
스트림의 요소들을 다른 컬렉션(List, Set, Map 등)으로 변환하거나, 집계 연산을 수행할 때 사용된다.
🔹 collect() 메소드
<R> R collect(Collector<? super T, A, R> collector)
- Collector를 사용하여 스트림의 요소를 리스트, 집합, 맵 등으로 변환 가능
- Collectors 유틸리티 클래스에서 다양한 Collector를 제공
1️⃣ 리스트 또는 셋으로 변환
List<String> names = students.stream()
.map(Student::getName)
.collect(Collectors.toList());
Set<Integer> scores = students.stream()
.map(Student::getScore)
.collect(Collectors.toSet());
2️⃣ Map으로 변환
Map<String, Integer> studentMap = students.stream()
.collect(Collectors.toMap(
Student::getName, // Key: 학생 이름
Student::getScore // Value: 학생 점수
));
주의: toMap()을 사용할 때 중복된 키가 발생하면 IllegalStateException이 발생할 수 있다.
해결 방법: toMap()의 세 번째 인자로 (oldValue, newValue) -> newValue 제공.
3️⃣ 그룹핑 (GroupBy)
요소들을 특정 그룹으로 묶을 때 Collectors.groupingBy()를 사용한다.
Map<String, List<Student>> studentsByGender = students.stream()
.collect(Collectors.groupingBy(Student::getGender));
결과
{
"남자": [Student1, Student2],
"여자": [Student3, Student4]
}
4️⃣ 그룹별 집계
Map<String, Double> avgScoreByGender = students.stream()
.collect(Collectors.groupingBy(
Student::getGender,
Collectors.averagingDouble(Student::getScore)
));
결과
{
"남자": 90.5,
"여자": 88.0
}
✅ 정리
기능 | 메소드 | 설명 |
기본 집계 | count(), sum(), average(), max(), min() | 요소 개수, 합, 평균, 최댓값, 최솟값 |
커스텀 집계 | reduce() | 사용자 정의 방식으로 요소 축소 |
요소 수집 | collect() | 리스트, 셋, 맵 등으로 변환 |
그룹핑 | groupingBy() | 특정 기준으로 그룹핑 |
그룹별 집계 | groupingBy() + averagingDouble() | 그룹별 평균, 합, 개수 구하기 |
💡 스트림을 활용하면 데이터를 더욱 직관적으로 필터링, 변환, 집계할 수 있다!
참조:
이것이 자바다 _ 신용권
'Web Programming Language > JAVA' 카테고리의 다른 글
스트림(Stream) 활용 - 요소 병렬 처리(Parallel Processing) (0) | 2025.03.06 |
---|---|
스트림(Stream) 활용 - 요소 정렬, 루핑(유소 개별 처리), 매칭(조건 만족 여부) (1) | 2025.03.06 |
스트림(Stream) 활용 - 리소스로부터 스트림 얻기, 요소 걸러내기(필터링), 요소 변환(매핑) (0) | 2025.03.06 |
스트림(Stream) - 스트림, 내부 반복자, 중간 처리와 최종 처리 (0) | 2025.03.06 |
람다식(Lambda Expression) - 메소드 참조, 생성자 참조 (1) | 2025.03.05 |
댓글