📚 3장. 스트림(Stream) 고급 중간 연산 정리
🎯 설명으로 이해하는 스트림 고급 중간 연산
스트림에서 자주 사용하는 중간 연산 중 고급 개념 13가지를 정리합니다.
1. map()
설명: 각 요소를 지정된 함수로 변환하여 새로운 스트림을 생성합니다.
용도: 값을 가공하거나 속성만 추출할 때 유용합니다.
List<String> list = Arrays.asList("a", "b", "c");
list.stream()
.map(s -> s.toUpperCase())
.forEach(System.out::println);
실행 결과:
A
B
C
코드 분석:
map()
: 각 요소를 대문자로 변환forEach()
: 변환된 결과를 출력
2. flatMap()
설명: 각 요소를 여러 요소로 바꾸고, 이들을 하나의 스트림으로 평탄화(flatten)합니다.
용도: 리스트 안의 리스트처럼 중첩된 구조를 펼칠 때 사용합니다.
List<List<String>> list = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d")
);
list.stream()
.flatMap(Collection::stream)
.forEach(System.out::println);
실행 결과:
a
b
c
d
코드 분석:
flatMap(Collection::stream)
: 리스트 내부 리스트들을 하나의 스트림으로 병합forEach()
: 병합된 스트림을 출력
추가 설명: map()
과 달리 flatMap()
은 다수의 스트림을 병합하는 역할을 함
3. peek()
설명: 중간 연산 과정 중 각 요소를 살펴볼 수 있게 도와주는 디버깅 용 메서드입니다.
용도: 스트림 처리 과정 중간의 상태를 확인할 때 사용합니다.
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.stream()
.peek(s -> System.out.println("Before: " + s))
.map(String::toUpperCase)
.peek(s -> System.out.println("After: " + s))
.collect(Collectors.toList());
실행 결과:
Before: apple
After: APPLE
Before: banana
After: BANANA
Before: cherry
After: CHERRY
코드 분석:
peek()
: 중간 흐름을 로그처럼 확인 (변환 전과 후)map()
: 대문자로 변환collect()
: 최종 리스트로 수집
추가 설명: peek()
는 디버깅 목적이기 때문에 실제 로직에 영향은 없음
4. filter()
설명: 주어진 조건에 해당하는 요소만 통과시킵니다.
용도: 특정 조건에 맞는 데이터만 추출할 때 사용합니다.
List<String> fruits = Arrays.asList("apple", "banana", "blueberry", "cherry");
fruits.stream()
.filter(fruit -> fruit.startsWith("b"))
.forEach(System.out::println);
실행 결과:
banana
blueberry
코드 분석:
filter()
: 'b'로 시작하는 문자열만 통과forEach()
: 통과한 항목 출력
추가 설명: 조건은 fruit -> fruit.startsWith("b")
와 같이 람다식으로 자유롭게 지정 가능
5. distinct()
설명: 중복된 요소를 제거하고 유일한 값만 남깁니다.
용도: 중복된 데이터를 제거하고 싶을 때 사용합니다.
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);
numbers.stream()
.distinct()
.forEach(System.out::println);
실행 결과:
1
2
3
코드 분석:
distinct()
: 중복 제거forEach()
: 고유 값 출력
6. sorted()
설명: 요소를 기본 또는 사용자 정의 기준에 따라 정렬합니다.
용도: 정렬된 데이터가 필요한 경우 사용합니다.
List<String> words = Arrays.asList("banana", "apple", "cherry");
words.stream()
.sorted()
.forEach(System.out::println);
실행 결과:
apple
banana
cherry
코드 분석:
sorted()
: 알파벳 오름차순 정렬forEach()
: 정렬 결과 출력
7. limit(n)
설명: 스트림에서 앞에서 n개만 남기고 나머지는 제거합니다.
용도: 페이징 처리나 일부만 미리보기 출력할 때 사용합니다.
List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);
numbers.stream()
.limit(3)
.forEach(System.out::println);
실행 결과:
10
20
30
코드 분석:
limit(3)
: 앞에서 3개의 요소만 남긴다forEach()
: 결과 출력
8. skip(n)
설명: 스트림에서 앞의 n개를 건너뛰고 나머지를 사용합니다.
용도: 페이징 처리 시 offset처럼 사용합니다.
List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);
numbers.stream()
.skip(2)
.forEach(System.out::println);
실행 결과:
30
40
50
코드 분석:
skip(2)
: 앞의 2개 요소를 건너뛴다forEach()
: 나머지 출력
9. anyMatch()
설명: 하나라도 조건을 만족하는 요소가 있으면 true를 반환합니다.
용도: 조건에 맞는 요소가 존재하는지만 확인할 때 사용합니다.
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEven = nums.stream()
.anyMatch(n -> n % 2 == 0);
System.out.println(hasEven);
실행 결과:
true
코드 분석:
anyMatch()
: 짝수가 하나라도 있으면 true 반환
10. allMatch()
설명: 모든 요소가 조건을 만족하면 true를 반환합니다.
용도: 전체 요소가 특정 조건을 만족하는지 검증할 때 사용합니다.
List<Integer> nums = Arrays.asList(2, 4, 6);
boolean allEven = nums.stream()
.allMatch(n -> n % 2 == 0);
System.out.println(allEven);
실행 결과:
true
코드 분석:
allMatch()
: 모든 수가 짝수라면 true 반환
11. noneMatch()
설명: 조건을 만족하는 요소가 하나도 없으면 true를 반환합니다.
용도: 특정 조건을 아예 만족하지 않는지 확인할 때 사용합니다.
List<Integer> nums = Arrays.asList(1, 3, 5);
boolean noEven = nums.stream()
.noneMatch(n -> n % 2 == 0);
System.out.println(noEven);
실행 결과:
true
코드 분석:
noneMatch()
: 짝수가 하나도 없으므로 true 반환
12. findFirst()
설명: 스트림에서 첫 번째 요소를 Optional로 반환합니다.
용도: 가장 앞에 있는 값을 꺼낼 때 사용합니다.
Optional<String> first = Stream.of("a", "b", "c")
.findFirst();
first.ifPresent(System.out::println);
실행 결과:
a
코드 분석:
findFirst()
: 첫 번째 요소를 Optional로 감싸서 반환ifPresent()
: 값이 있으면 출력
13. reduce()
설명: 스트림의 요소를 하나로 축소(집계)합니다. 합계, 곱셈, 최대값 등에 활용됩니다.
용도: 모든 요소를 누적 처리하여 단일 값을 만들고 싶을 때 사용합니다.
int sum = Stream.of(1, 2, 3, 4)
.reduce(0, Integer::sum);
System.out.println(sum);
실행 결과:
10
코드 분석:
reduce()
: 누산기(accumulator)를 통해 전체 합계 계산
0 댓글