Java Streams API의 중간 연산은 스트림을 변환하거나 필터링하는 작업을 수행하며, 항상 또 다른 스트림을 반환합니다. 중간 연산은 지연 평가(lazy evaluation) 방식으로 동작하여, 최종 연산이 호출되기 전까지는 실제로 수행되지 않습니다. 이는 스트림 파이프라인의 효율성을 높이고, 필요 이상의 연산을 피하는 데 도움을 줍니다.
다음은 주요 중간 연산과 그 동작 방식에 대한 자세한 설명입니다.
주요 중간 연산
- filter
- 주어진 조건(predicate)에 맞는 요소들만 포함하는 스트림을 반환합니다.
- 사용 예:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// 결과: [2, 4]
- map
- 각 요소를 주어진 함수에 따라 변환하여 새로운 요소로 구성된 스트림을 반환합니다.
- 사용 예:
List<String> words = Arrays.asList("hello", "world");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
// 결과: [5, 5]
- flatMap
- 각 요소를 스트림으로 변환하고, 이 스트림들을 하나의 평면화된 스트림으로 병합합니다.
- 사용 예:
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d"));
List<String> flatList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// 결과: [a, b, c, d]
- distinct
- 중복된 요소를 제거한 스트림을 반환합니다.
- 사용 예:
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
// 결과: [1, 2, 3]
- sorted
- 스트림의 요소를 정렬된 순서로 반환합니다. 기본 정렬 순서나 사용자 정의 비교자(comparator)를 사용할 수 있습니다.
- 사용 예:
List<String> words = Arrays.asList("banana", "apple", "cherry");
List<String> sortedWords = words.stream()
.sorted()
.collect(Collectors.toList());
// 결과: [apple, banana, cherry]
- peek
- 각 요소를 소비하지 않고, 중간에 요소를 보고 싶을 때 사용합니다. 주로 디버깅 목적으로 사용됩니다.
- 사용 예:
List<String> words = Arrays.asList("one", "two", "three");
words.stream()
.peek(System.out::println)
.map(String::toUpperCase)
.collect(Collectors.toList());
// 결과: 출력 - one, two, three
- limit
- 스트림의 요소 개수를 제한합니다.
- 사용 예:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
// 결과: [1, 2, 3]
- skip
- 처음 n개의 요소를 건너뛰고 나머지 요소들로 구성된 스트림을 반환합니다.
- 사용 예:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
.skip(2)
.collect(Collectors.toList());
// 결과: [3, 4, 5]
지연 평가(lazy evaluation)
중간 연산은 최종 연산이 호출될 때까지 실제로 수행되지 않습니다. 이는 스트림 파이프라인의 성능을 최적화하는 데 도움을 줍니다. 예를 들어, 스트림의 모든 요소에 대해 filter와 map 연산이 정의되어 있더라도, 최종 연산이 호출될 때 필요한 만큼의 요소에 대해서만 연산이 수행됩니다.
중간 연산의 연결
여러 중간 연산을 연결하여 복잡한 데이터 처리 파이프라인을 만들 수 있습니다. 이러한 파이프라인은 각 중간 연산이 다음 연산으로 스트림을 전달하면서 자연스럽게 연결됩니다.
예제:
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
List<String> result = words.stream()
.filter(word -> word.startsWith("a"))
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
// 결과: [APPLE]
위의 예제에서, 스트림은 filter, map, sorted 연산을 거쳐 최종적으로 결과 리스트를 생성합니다.
이처럼 Java Streams API의 중간 연산은 데이터 처리 파이프라인을 구성하는 중요한 요소로, 다양한 데이터를 효율적으로 변환하고 필터링하는 데 사용됩니다.
'프로그래밍 > JAVA' 카테고리의 다른 글
Java stream 의 Optional.orElseThrow (0) | 2024.07.28 |
---|---|
Multi Datasource 를 이용한 database routing 전략 (0) | 2024.07.06 |
Java Streams API - 3 (0) | 2024.05.26 |
Java Streams API - 1 (0) | 2024.05.26 |