Stream의 객체를 구성하고자 할 때 "Stream 생성 → 중간 연산→ 최종 연산"의 세 단계의 과정을 통해서 Stream의 구성이 이루어집니다.
이번 포스팅에서는 Stream의 요소를 다른 형태로 수집하는 최종 연산인 collect에 대해 알아보겠습니다.
collect❓
Stream의 최종 연산자 중 가장 복잡하지만, 가장 유용하게 사용할 수 있는 것이 바로 collect()입니다.
collect()는 일반적으로 List, Set, Map 등의 Collection으로 수집하거나, 요소를 결합하여 단일 결과를 생성할 때 사용됩니다.
collect 메서드의 시그니처
<R, A> R collect(Collector<? super T, A, R> collector);
- R : 결과 타입 (저장될 컬렉션)
- A : 중간 누적(accumulator)
- T : 스트림의 요소 타입
collect 메서드는 sort() 함수의Comparator처럼 collect() 시 Collector 인터페이스를 사용하여 다양한 수집 전략을 지원합니다.
정리하자면 collect는 Collector를 사용해 스트림의 요소를 다른 형태로 수집하는 최종 연산입니다.
collect() | 스트림의 최종연산, 매개변수로 Collector를 필요로합니다. |
Collector | 인터페이스로 Collector는 이를 구현해야합니다. |
Collectors | 클래스로 static 메서드로 미리 구현한 Collector 를 제공합니다. |
Collectors Class : 수집
Collector.toList()
import java.util.*;
import java.util.stream.*;
public class CollectExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Park", "Son", "Kim", "Choi");
List<String> namesList = names.stream()
.collect(Collectors.toList());
System.out.println("List: " + namesList);
}
}
스트림의 모든 요소를 List로 변환합니다.
Collectors.toSet()
import java.util.*;
import java.util.stream.*;
public class CollectExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Park", "Son", "Kim", "Choi");
Set<String> namesSet = names.stream()
.collect(Collectors.toSet());
System.out.println("Set: " + namesSet);
}
}
스트림의 모든 요소를 Set로 변환합니다.
Collectors.toMap()
import java.util.*;
import java.util.stream.*;
public class CollectExample {
public static void main(String[] args) {
Stream<String> stream2 = Stream.of("1", "2", "3", "4", "5");
Map<Integer, String> streamToMap = stream2.collect(Collectors.toMap((i) -> Integer.parseInt(i), (i) -> "\""+(i)+"\""));
System.out.println("streamToMap = " + streamToMap);
}
}
스트림의 요소들을 맵(Map)으로 수집하는 데 사용되는 메서드입니다.
객체의 어떤 필드를 key로 사용할지와 어 떤 필드를 value로 사용할지 지정해줘야 합니다.
Collectors Class : 문자열 결합
joining()
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class JoiningExample {
public static void main(String[] args) {
Stream<String> wordsStream = Stream.of("Hello", "World", "Java");
String result = wordsStream.collect(Collectors.joining(" "));
String result2 = wordsStream.collect(Collectors.joining(", ", "[", "]"));
System.out.println(result); // 출력: Hello World Java
System.out.println(result2); // 출력: [Hello,World,Java]
}
}
Stream의 문자열 요소를 하나의 문자열로 결합합니다.
result2 처럼 문자열을 결합할 때 접두사와 접미사를 추가할 수 있습니다.
스트림의 요소들을 결합하여 하나의 문자열로 반환하기 때문에 반환 값은 String입니다.
Collectors Class : 통계 수집
counting
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CollectorsExample {
public static void main(String[] args) {
List<String> wordsStream = Arrays.asList("Hello", "World", "Java");
long count = wordsStream.stream().collect(Collectors.counting());
System.out.println("Count: " + count); // 3
}
}
Stream의 요소 수를 셉니다.
summingInt
import java.util.*;
import java.util.stream.*;
public class SummingIntExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
// 각 문자열의 길이를 합산하여 총 글자 수 계산
int totalLength = words.stream().collect(Collectors.summingInt(String::length));
System.out.println("Total length: " + totalLength);
}
}
스트림의 요소의 합을 계산합니다. summingInt 말고도 summingDouble, summingLong 등이 있습니다.
averagingInt
import java.util.*;
import java.util.stream.*;
public class AveragingIntExample {
public static void main(String[] args) {
List<Integer> scores = Arrays.asList(80, 90, 75, 85, 95);
// 평균 점수 계산
double averageScore = scores.stream().collect(Collectors.averagingInt(score -> score));
System.out.println(averageScore); // 결과 : 85.0
}
}
스트림의 요소에 대한 평균값을 계산합니다.
summarizingInt
import java.util.*;
import java.util.stream.*;
public class SummarizingIntExample {
public static void main(String[] args) {
List<Integer> scores = Arrays.asList(80, 90, 75, 85, 95);
// 점수에 대한 통계 정보 계산
IntSummaryStatistics stats = scores.stream().collect(Collectors.summarizingInt(score -> score));
System.out.println("Statistics: " + stats);
}
}
스트림의 요소에 대한 통계 정보를 계산하는 데 사용됩니다.
정수형 데이터에 대해 최소, 최대, 합계, 평균, 요소 수를 포함한 통계를 계산합니다.
Collectors Class : 그룹화 및 분할
groupingBy()
import java.util.*;
import java.util.stream.*;
public class GroupingByExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date", "apple");
// 과일을 종류별로 그룹화
Map<Character, List<String>> groupedByFirstLetter = fruits.stream().collect(Collectors.groupingBy(fruit -> fruit.charAt(0)));
System.out.println("Grouped by first letter: " + groupedByFirstLetter);
}
}
groupingBy() 메서드는 스트림의 요소를 주어진 함수에 따라 그룹화합니다. 결과는 Map에 담겨 반환됩니다.
위 코드는 리스트의 각 과일을 첫 글자(charAt(0))로 그룹화하기 위해 스트림을 생성한 후, groupingBy() 메서드를 사용하여 이들을 그룹화합니다. 마지막으로 그룹화된 결과를 출력합니다. 위 코드의 결과는 다음과 같습니다.
Grouped by first letter: {a=[apple, apple], b=[banana], c=[cherry], d=[date]}
partitioningBy()
import java.util.*;
import java.util.stream.*;
public class PartitioningByExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 홀수와 짝수로 분할
Map<Boolean, List<Integer>> partitioned = numbers.stream().collect(Collectors.partitioningBy(number -> number % 2 == 0));
System.out.println("Partitioned numbers: " + partitioned);
}
}
Collectors.partitioningBy() 메서드는 스트림의 요소를 주어진 조건에 따라 두 그룹으로 분할하는 데 사용됩니다.
두 그룹은 true와 false 값을 가지는 맵 형태로 반환됩니다. 조건을 만족하는 요소는 true 그룹에, 만족하지 않는 요소는 false 그룹에 속합니다.
위 코드의 결과는 다음과 같습니다.
Partitioned numbers: {false=[1, 3, 5, 7, 9], true=[2, 4, 6, 8, 10]}
Collectors Class : 리듀싱 및 요약
reducing
import java.util.*;
import java.util.stream.*;
public class ReducingExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 정수 요소들의 합 계산
Optional<Integer> sum = numbers.stream().collect(Collectors.reducing((x, y) -> x + y));
System.out.println("Sum: " + sum.orElse(0));
}
}
Collectors.reducing() 메서드는 스트림의 요소를 리듀스 연산을 사용하여 하나의 결과로 결합하는 데 사용됩니다.
reducing 메서드는 초기값을 사용하여 reduce 연산을 수행하거나, 초기값이 없는 경우 첫 번 째요소를 시작값으로 사용하여 reduce연산을 수행합니다.
위 코드는 리스트의 각 문자열 요소를 쉼표로 구분하여 결합하기 위해 스트림을 생성한 후, reducing() 메서드를 사용하여 이들을 결합합니다. 마지막으로 결합된 문자열을 출력합니다.
위 예제 코드의 출력은 다음과 같습니다.
Sum: 15
reduce 연산의 결과로 얻은 값이 존재할 수도 있고, 없을 수도 있기 때문에 반환 값은 Optional<T> 입니다.
스트림 API의 Collectors 클래스는 자바 프로그래밍에서 데이터 처리를 더욱 간편하고 효율적으로 만들어주는 강력한 도구입니다.
이 클래스는 다양한 컬렉션 형식으로 데이터를 수집하고 처리할 수 있는 다양한 메서드를 제공하여 개발자들이 자신의 요구에 맞게 유연하게 작업할 수 있도록 도와줍니다.
'Language > Java' 카테고리의 다른 글
[JAVA] Collections.sort vs Arrays.sort 차이점 알아보기 (0) | 2024.05.31 |
---|---|
[JAVA] contains() 메소드 알아보기 (문자열 포함 여부 확인) (0) | 2024.05.23 |
[JAVA] Optional 클래스에 대해 알아보기 (0) | 2024.05.19 |
[JAVA] Stream API에 대해 알아보기 _ Stream 최종 연산(집계) (4/5) (0) | 2024.05.18 |
[JAVA] Stream API에 대해 알아보기 _ Stream 중간 연산(가공) (3/5) (0) | 2024.05.17 |