Java의 Stream API는 Java 8에서 도입된 기능으로, 컬렉션 데이터를 다루는 데 있어 더 효율적이고 선언적인 방법을 제공합니다. Stream API는 컬렉션에 저장된 데이터를 처리(필터링, 정렬, 변환 등)하는데 유용하며, 함수형 프로그래밍 스타일을 지원합니다.
기존의 입출력 스트림과는 전혀 다른 개념이니 혼동하지 않도록 합니다.
주요 개념
- Stream:
- 데이터의 순차적인 흐름을 나타냅니다. 컬렉션에서 데이터를 추출하여 스트림을 생성할 수 있습니다.
- 중간 연산 (Intermediate Operations):
- 스트림을 변환하지만, 결과를 최종적으로 반환하지 않는 연산입니다. 중간 연산은 항상 또 다른 스트림을 반환하며, 이는 체이닝(chaining)될 수 있습니다. 예:
filter
,map
,sorted
.
- 최종 연산 (Terminal Operations):
- 스트림을 처리하고 결과를 반환합니다. 최종 연산이 호출되면 스트림의 데이터가 소비되며, 이후에 스트림을 다시 사용할 수 없습니다. 예:
forEach
,collect
,reduce
.
예제 1: Count
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> r1 = names.stream().filter(name -> name.length() > 3).toList();
r1.forEach(s -> System.out.println(s));
Long r2 = names.stream().filter(name -> name.length() > 3).count();
System.out.println(r2);
- 설명:
filter
: 이름의 길이가 3보다 큰 요소만 필터링합니다.toList
: 필터링된 결과를 리스트로 반환합니다.forEach
: 결과를 하나씩 출력합니다.count
: 필터링된 요소의 개수를 세고 출력합니다.
- 결과:
- 필터링된 리스트 출력: "Alice", "Charlie", "David"
- 필터링된 요소의 개수 출력:
3
예제 2: Sort
List<Integer> nums = Arrays.asList(5, 3, 1, 4, 2, 5);
// 정렬을 한 뒤, 중복을 제거하고, 반복문으로 출력한다.
nums.stream().sorted().distinct().forEach(integer -> System.out.println(integer));
- 설명:
sorted
: 리스트의 요소를 오름차순으로 정렬합니다.distinct
: 중복된 요소를 제거합니다.forEach
: 정렬되고 중복이 제거된 요소를 하나씩 출력합니다.
- 결과:
- 출력: 1, 2, 3, 4, 5
예제 3: Map
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> newNames = names.stream().map(name -> name.toLowerCase())
.filter(name -> name.length() > 3)
.toList();
newNames.forEach(name -> System.out.println(name));
- 설명:
map
: 각 이름을 소문자로 변환합니다.filter
: 이름의 길이가 3보다 큰 요소만 필터링합니다.toList
: 필터링된 결과를 리스트로 반환합니다.forEach
: 결과를 하나씩 출력합니다.
- 결과:
- 출력: "alice", "charlie", "david"
예제 4: Group
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "anna");
// 리턴 타입 : Map<Character, List<String>>
// 최근 버전은 var로 모든 형을 대체해서 쓸 수 있게 패치되었다.
var groupData = names.stream()
.map(name -> name.toUpperCase())
.collect(Collectors.groupingBy(name -> name.charAt(0)));
System.out.println(groupData);
- 설명:
map
: 각 이름을 대문자로 변환합니다.collect
: 이름의 첫 글자를 기준으로 그룹화하여Map
으로 반환합니다.Collectors.groupingBy
: 그룹화를 수행하는 수집기(collector)를 사용합니다.
- 결과:
- 출력: {A=[ALICE, ANNA], B=[BOB], C=[CHARLIE], D=[DAVID]}
예제 5: Reduce (조인)
List<Integer> nums = Arrays.asList(1, 2, 3, 4);
int sum1 = nums.stream().mapToInt(x -> x).sum();
System.out.println(sum1);
int sum2 = nums.stream().reduce(5, (prev, next) -> {
System.out.println("prev : " + prev);
System.out.println("next : " + next);
System.out.println("----------");
return prev + next;
});
System.out.println(sum2);
- 설명:
mapToInt
및sum
: 스트림의 모든 요소를 정수형으로 변환하고 합계를 계산합니다.reduce
: 초기값5
를 가지고, 스트림의 모든 요소를 더하여 최종 합계를 계산합니다. 중간 값(prev
와next
)을 출력합니다.
- 결과:
sum1
: 10 (1 + 2 + 3 + 4)sum2
: 15 (5 + 1 + 2 + 3 + 4)
Share article