# Java Stream API Java의 **Stream API**는 컬렉션, 배열 등에서 요소를 효율적으로 처리할 수 있도록 제공되는 기능이다. Stream은 **중간 연산(Intermediate Operation)**과 **최종 연산(Terminal Operation)**으로 나뉘며, 스트림을 사용하면 **반복문 없이 데이터 변환, 필터링, 집계 등을 간결하게 처리 가능**하다. ## Stream API 메서드 ### 스트림 생성 메서드 | 메서드 | 설명 | |--------|------| | `Stream.of(T... values)` | 여러 개의 값을 직접 입력하여 스트림 생성 | | `Stream.ofNullable(T t)` | 값이 `null`이면 비어있는 스트림 반환 | | `Arrays.stream(T[] array)` | 배열을 스트림으로 변환 | | `Collection.stream()` | 컬렉션(List, Set 등)에서 스트림 생성 | | `Collection.parallelStream()` | 병렬 스트림 생성 | | `IntStream.range(int start, int end)` | 특정 범위의 숫자 스트림 생성 (end 미포함) | | `IntStream.rangeClosed(int start, int end)` | 특정 범위의 숫자 스트림 생성 (end 포함) | | `Stream.iterate(T seed, UnaryOperator f)` | 초기값과 람다식을 사용하여 무한 스트림 생성 | | `Stream.generate(Supplier s)` | Supplier를 사용해 무한 스트림 생성 | ### 필터링 및 매핑 (중간 연산) | 메서드 | 설명 | |--------|------| | `filter(Predicate predicate)` | 조건에 맞는 요소만 포함하는 스트림 반환 | | `map(Function mapper)` | 각 요소를 변환하여 새로운 스트림 생성 | | `flatMap(Function> mapper)` | 각 요소를 스트림으로 변환한 후 하나의 스트림으로 결합 | | `distinct()` | 중복 요소 제거 | | `sorted()` | 요소들을 정렬 (기본 정렬 기준 사용) | | `sorted(Comparator comparator)` | 지정한 비교자를 사용하여 정렬 | | `peek(Consumer action)` | 스트림의 각 요소를 확인 (디버깅용) | ### 요소 제한 및 조작 (중간 연산) | 메서드 | 설명 | |--------|------| | `limit(long maxSize)` | 지정된 개수만큼 요소를 제한 | | `skip(long n)` | 앞의 n개 요소를 건너뛰고 나머지 반환 | | `takeWhile(Predicate predicate)` | 조건을 만족하는 동안 요소를 유지하고 이후 요소는 제외 | | `dropWhile(Predicate predicate)` | 조건을 만족하는 동안 요소를 버리고 이후 요소만 유지 | ### 집계 및 종료 연산 (최종 연산) | 메서드 | 설명 | |--------|------| | `count()` | 스트림 내 요소 개수 반환 | | `min(Comparator comparator)` | 최소값 반환 | | `max(Comparator comparator)` | 최대값 반환 | | `findFirst()` | 첫 번째 요소 반환 (Optional) | | `findAny()` | 임의의 요소 반환 (Optional) | | `allMatch(Predicate predicate)` | 모든 요소가 조건을 만족하는지 검사 (boolean) | | `anyMatch(Predicate predicate)` | 하나 이상의 요소가 조건을 만족하는지 검사 (boolean) | | `noneMatch(Predicate predicate)` | 모든 요소가 조건을 만족하지 않는지 검사 (boolean) | | `forEach(Consumer action)` | 각 요소에 대해 작업 수행 (최종 연산) | ### 스트림을 컬렉션으로 변환 | 메서드 | 설명 | |--------|------| | `toArray()` | 스트림을 배열로 변환 | | `collect(Collectors.toList())` | 스트림을 리스트로 변환 | | `collect(Collectors.toSet())` | 스트림을 집합(Set)으로 변환 | | `collect(Collectors.toMap(Function, Function))` | 스트림을 Map으로 변환 | ### 요소를 조합하여 결과 생성 | 메서드 | 설명 | |--------|------| | `reduce(BinaryOperator accumulator)` | 요소를 하나의 값으로 축약 | | `reduce(T identity, BinaryOperator accumulator)` | 초기값을 사용하여 축약 | | `reduce(T identity, BiFunction accumulator, BinaryOperator combiner)` | 병렬 처리용 축약 연산 | ## Stream API 예제 ### 스트림 생성 및 변환 ```java import java.util.*; import java.util.stream.*; public class StreamExample { public static void main(String[] args) { // 리스트에서 스트림 생성 List names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // 이름 길이가 4 이상인 요소 필터링 List result = names.stream() .filter(name -> name.length() >= 4) .sorted() .collect(Collectors.toList()); System.out.println(result); // 출력: [Alice, Charlie, David] } } ``` ### `map()`을 이용한 변환 ```java List words = Arrays.asList("apple", "banana", "cherry"); List lengths = words.stream() .map(String::length) .collect(Collectors.toList()); System.out.println(lengths); // 출력: [5, 6, 6] ``` ### `flatMap()`을 이용한 중첩 리스트 평탄화 ```java List> listOfLists = Arrays.asList( Arrays.asList("a", "b"), Arrays.asList("c", "d"), Arrays.asList("e", "f") ); List flatList = listOfLists.stream() .flatMap(List::stream) .collect(Collectors.toList()); System.out.println(flatList); // 출력: [a, b, c, d, e, f] ``` ### `reduce()`를 이용한 합산 ```java List numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, Integer::sum); System.out.println(sum); // 출력: 15 ``` ### `groupingBy()`를 이용한 그룹화 ```java List items = Arrays.asList("apple", "banana", "apple", "orange", "banana"); Map itemCount = items.stream() .collect(Collectors.groupingBy(s -> s, Collectors.counting())); System.out.println(itemCount); // 출력: {banana=2, apple=2, orange=1} ``` ## 정리 - **Java Stream API**는 **중간 연산**과 **최종 연산**을 조합하여 데이터를 효과적으로 변환하고 처리하는 도구다. - **`filter()`**, **`map()`**, **`flatMap()`**을 사용하여 데이터를 가공할 수 있다. - **`collect()`**를 사용하여 스트림을 **리스트, 셋, 맵**으로 변환할 수 있다. - **`reduce()`**, **`groupingBy()`** 등의 메서드를 활용하면 데이터 집계를 손쉽게 수행할 수 있다. - 대량의 데이터를 **간결하고 효율적으로 처리하는 경우 Stream API를 적극 활용**하자!