Java Stream API에서 collect() 메서드는 스트림의 요소들을 컬렉션으로 집계하거나, 다양한 방식으로 결과를 처리할 때 사용됩니다. 주로 Collectors 유틸리티 클래스와 함께 사용되며, 리스트 변환, 그룹화, 조인, 맵핑 등의 기능을 제공합니다. 가장 많이 사용되는 컬렉는 Collectors.toList(), Collectors.toSet(), Collectors.toMap() 등이 있습니다.
주요 Collectors 메소드
1. 리스트(List)나 집합(Set)으로 변환 - toList(), toSet(), toMap()
스트림 결과를 List, Set, Map 등으로 변환 할 수 있습니다.
import java.util.*;
import java.util.stream.Collectors;
public class CollectExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "Apple");
// List로 수집
List<String> fruitList = fruits.stream()
.collect(Collectors.toList());
System.out.println("List: " + fruitList); // List: [Apple, Banana, Cherry, Apple]
// Set으로 수집 (중복 제거)
Set<String> fruitSet = fruits.stream()
.collect(Collectors.toSet());
System.out.println("Set: " + fruitSet); // Set: [Apple, Cherry, Banana]
}
}
스트림의 요소들을 Map으로 변환 하는 예제 입니다. Map은 키 중복시 에러가 발생합니다. 중복 발생 시 mergeFunction을 추가하여 해결 할 수 있습니다.
public class CollectExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "melon");
// 과일 이름을 길이로 매핑하여 Map으로 변환(키값 중복시 에러)
Map<String, Integer> fruitLengthMap = fruits.stream()
.collect(Collectors.toMap(fruit -> fruit, String::length)); // 이름을 키, 길이를 값으로
System.out.println("Map :" + fruitLengthMap); // Map :{Apple=5, Cherry=6, melon=5, Banana=6}
}
}
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name;
}
}
public class CollectExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 30),
new Person("David", 25)
);
Map<String, Integer> nameToAgeMap = people.stream()
.collect(Collectors.toMap(person -> person.name, person -> person.age));
System.out.println(nameToAgeMap); // {Alice=30, Bob=25, Charlie=30, David=25}
}
}
다음 예제는 mergeFunction을 추가하여 중복 문제를 해결 하는 예제입니다.
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name;
}
}
public class CollectExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 30),
new Person("Alice", 25)
);
Map<Integer, String> ageToNames = people.stream()
.collect(Collectors.toMap(
person -> person.age,
person -> person.name,
(existing, newValue) -> existing + ", " + newValue // 중복 Key 처리
));
System.out.println(ageToNames); // {25=Bob, Alice, 30=Alice, Charlie}
}
}
아래와 같이 List -> Map -> LinkedHashMap로 결과 값을 변환 할 수도 있다.
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name;
}
}
public class CollectExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 30),
new Person("David", 25)
);
Map<String, Integer> nameToAgeMap = people.stream()
.collect(Collectors.toMap(person -> person.name, person -> person.age));
LinkedHashMap<String, Integer> changeLinkedHashMap = nameToAgeMap.entrySet().stream()
.sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey()))
.collect(LinkedHashMap::new, (m, e) -> m.put(e.getKey(), e.getValue()), Map::putAll);
System.out.println(changeLinkedHashMap); // {Alice=30, Bob=25, Charlie=30, David=25}
}
}
2. 특정 타입의 컬렉션으로 변환 - toCollection()
public class CollectExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry", "Apple");
// ArrayList로 변환
ArrayList<String> arrayList = fruits.stream()
.collect(Collectors.toCollection(ArrayList::new));
System.out.println("arrayList: " + arrayList); // arrayList: [Apple, Banana, Cherry, Apple]
// treeSet으로 변환
TreeSet<String> treeSet = fruits.stream()
.collect(Collectors.toCollection(TreeSet::new));
System.out.println("treeSet: " + treeSet); // treeSet: [Apple, Banana, Cherry]
}
}
3.문자열 결합 - joining()
스트림 요소를 하나의 문자열로 합칩니다.
public class CollectExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("Java", "Stream", "API");
String result = words.stream()
.collect(Collectors.joining(", "));
System.out.println(result); // Java, Stream, API
}
}
4. 값 합산, 평균, 통계 - summingInt(), averagingInt(), summarizingInt()
public class CollectExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(3, 5, 8, 10);
int sum = numbers.stream()
.collect(Collectors.summingInt(Integer::intValue));
double avg = numbers.stream()
.collect(Collectors.averagingInt(Integer::intValue));
IntSummaryStatistics stats = numbers.stream()
.collect(Collectors.summarizingInt(Integer::intValue));
// Sum: 26
System.out.println("Sum: " + sum);
// Avg: 6.5
System.out.println("Avg: " + avg);
// Stats: IntSummaryStatistics{count=4, sum=26, min=3, average=6.500000, max=10}
System.out.println("Stats: " + stats);
}
}
5. 그룹화 - groupingBy()
public class CollectExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Ava", "Bob", "Charlie", "Chan", "David", "Eva");
// 첫 글자를 기준으로 이름 그룹화
Map<Character, List<String>> groupedByFirstLetter = names.stream()
.collect(Collectors.groupingBy(name -> name.charAt(0))); // 첫 글자를 기준으로 그룹화
System.out.println(groupedByFirstLetter);
// {A=[Alice, Ava], B=[Bob], C=[Charlie, Chan], D=[David], E=[Eva]}
}
}
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name;
}
}
public class CollectExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 30),
new Person("David", 25)
);
// 나이별 그룹화
Map<Integer, List<Person>> groupedByAge = people.stream()
.collect(Collectors.groupingBy(person -> person.age));
// {25=[Bob, David], 30=[Alice, Charlie]}
System.out.println(groupedByAge);
}
}
6. 그룹화 + 개수 세기 - groupingBy() + counting()
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name;
}
}
public class CollectExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 30),
new Person("David", 25)
);
Map<Integer, Long> countByAge = people.stream()
.collect(Collectors.groupingBy(person -> person.age, Collectors.counting()));
System.out.println(countByAge); // {30=2, 25=2}
}
}
7. 조건에 따른 분할 - partitioningBy()
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name;
}
}
public class CollectExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 30),
new Person("David", 25)
);
Map<Boolean, List<Person>> partitioned = people.stream()
.collect(Collectors.partitioningBy(person -> person.age >= 30));
System.out.println(partitioned);
}
}
정리
collect()는 Java Stream API에서 매우 중요한 메서드로, 다양한 방식으로 데이터를 집계하는 데 사용됩니다. Collectors.toList(), Collectors.toSet(), Collectors.toMap() 외에도 그룹화, 합산, 평균 계산, 요소 결합 등 여러 가지 유용한 방법들이 제공되므로 필요에 따라 적절히 활용할 수 있습니다.
'BackEnd > JAVA' 카테고리의 다른 글
[JAVA] 정규식 사용 정리 (0) | 2025.02.20 |
---|---|
[JAVA] Stream API 생성과 사용법 정리 (2) | 2025.02.15 |
[JAVA] Checked Exception과 Unchecked Exception 차이점 (0) | 2025.02.13 |