다음은 네이버 블로그 원문을 Velog 스타일에 맞춰 재구성한 기술 블로그 글입니다.
Java 8부터 도입된 Stream API는 컬렉션 및 배열의 데이터를 함수형으로 처리할 수 있는 강력한 도구이다. 기존의 반복문과 Iterator 방식의 코드 복잡성, 가독성 저하 문제를 해결하며, 데이터 소스에 대한 추상화를 통해 일관된 방식으로 데이터를 다룰 수 있게 한다.
본 글에서는 Java Stream API의 정의, 주요 특징, 그리고 중간 연산 및 최종 연산의 종류를 상세히 다룬다.
Stream은 Java 8에서 추가된 기술로, 람다 표현식을 활용하여 배열 및 컬렉션을 함수형으로 간결하게 처리한다. 이는 데이터 소스를 추상화하여, 데이터 타입에 관계없이 동일한 방식으로 데이터를 다룰 수 있게 함으로써 코드의 재사용성을 높인다. 기존의 for문이나 Iterator 사용 시 발생하던 코드의 길이 증가 및 가독성 저하 문제를 개선한다.
forEach()와 같은 메소드는 데이터 소스의 모든 요소에 람다식을 적용하는 등 내부적으로 반복을 처리한다.parallelStream() 메소드를 통해 손쉽게 병렬 처리를 구현할 수 있다.IntStream, LongStream, DoubleStream과 같은 기본형 스트림을 제공하여 Stream<Integer>와 같은 박싱된(boxed) 스트림보다 효율적인 작업을 지원한다.Stream 연산은 크게 중간 연산과 최종 연산으로 구분된다.
중간 연산은 Stream을 반환하여 여러 연산을 연결할 수 있게 한다.
distinct(): Stream 내 중복 요소를 제거한다.filter(Predicate<T> predicate): 주어진 조건식에 맞는 요소만으로 Stream을 구성한다.limit(long maxSize): Stream의 요소 개수를 지정된 maxSize로 제한한다.skip(long n): Stream의 앞에서부터 n개의 요소를 건너뛴다.sorted() / sorted(Comparator<T> comparator): Stream의 요소를 정렬한다.map(Function<T, R> mapper): Stream의 각 요소를 특정 조건에 따라 다른 값으로 변환하여 새로운 Stream을 생성한다.최종 연산은 Stream을 소모하며, Stream이 아닌 단일 값 또는 다른 형태의 결과를 반환한다.
forEach(Consumer<T> action) / forEachOrdered(Consumer<T> action): Stream의 각 요소에 지정된 작업을 수행한다.count(): Stream의 요소 개수를 반환한다.max(Comparator<T> comparator) / min(Comparator<T> comparator): Stream 요소 중 최대값 또는 최소값을 반환한다.findAny(): Stream에서 임의의 요소를 하나 반환한다 (병렬 스트림의 경우 첫 번째 요소를 보장하지 않음).findFirst(): Stream의 첫 번째 요소를 반환한다.allMatch(Predicate<T> predicate): Stream의 모든 요소가 조건을 만족하는지 확인한다.anyMatch(Predicate<T> predicate): Stream의 요소 중 하나라도 조건을 만족하는지 확인한다.noneMatch(Predicate<T> predicate): Stream의 모든 요소가 조건을 만족하지 않는지 확인한다.toArray(): Stream의 요소를 배열로 반환한다.reduce(BinaryOperator<T> accumulator): Stream의 요소를 하나씩 줄여가며 누적 연산을 수행한다.collect(Collector<T, A, R> collector): Stream의 요소를 수집하여 원하는 자료형 (List, Set, Map 등)으로 반환한다.Java Stream API는 Java 8 이후 함수형 프로그래밍 스타일을 도입하여 데이터 처리 방식을 혁신한 기술이다. 복잡한 반복 로직을 간결하고 가독성 높은 코드로 대체하며, 원본 데이터의 불변성을 유지하고 지연 연산을 통해 효율성을 높인다. 또한, 병렬 처리를 손쉽게 구현할 수 있어 대규모 데이터 처리에도 유리하다.
Stream API의 핵심은 '데이터의 흐름'을 처리하는 방식에 있으며, 중간 연산을 통해 데이터 파이프라인을 구축하고 최종 연산을 통해 원하는 결과를 도출하는 패턴을 이해하는 것이 중요하다. 현대 Java 개발에서 Stream API는 필수적인 요소로 자리매김하고 있으며, 적극적인 활용을 통해 보다 효율적이고 유지보수하기 쉬운 코드를 작성할 수 있다.