Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

자바 스트림(Stream)이란? 핵심 개념과 실전 예제 총정리


스트림(Stream)은 소스(source)로부터 일련의 객체 시퀀스를 나타내며, 집계 연산(aggregate operations)을 지원하는 자바의 핵심 API입니다. 데이터를 선언형으로 간결하게 처리할 수 있어 현대 자바 개발에서 필수적인 요소로 자리 잡았습니다.

스트림의 주요 특징

  • 요소의 시퀀스 − 스트림은 특정 타입의 요소들을 순차적으로 제공합니다. 요소는 필요할 때(on demand) 가져오거나 계산되며, 스트림 자체는 요소를 저장하지 않습니다.

  • 소스(Source) − 스트림은 컬렉션(Collection), 배열(Array), I/O 리소스 등을 입력 소스로 사용합니다.

  • 집계 연산 − filter, map, limit, reduce, find, match 등 다양한 집계 연산을 지원하여 복잡한 데이터 처리 로직을 간결하게 표현할 수 있습니다.

  • 파이프라이닝(Pipelining) − 대부분의 스트림 연산은 스트림 자신을 반환하므로 여러 연산을 연결해 하나의 파이프라인처럼 구성할 수 있습니다. 이러한 연산을 중간 연산(intermediate operation)이라고 하며, 입력을 받아 처리한 뒤 그 결과를 다음 단계로 전달합니다. 파이프라인의 끝에는 collect() 같은 최종 연산(terminal operation)을 호출해 스트림 처리를 종료합니다.

  • 자동 반복 − 스트림은 내부적으로 소스 요소에 대한 반복을 자동으로 수행합니다. 컬렉션에서처럼 개발자가 명시적으로 반복문을 작성할 필요가 없습니다.

예제 1: 스트림을 TreeSet으로 수집하기

다음 예제는 문자열 스트림을 생성한 뒤, collect() 메서드와 Collectors.toCollection()을 사용해 TreeSet으로 변환합니다. TreeSet은 중복을 자동으로 제거하고 정렬된 순서로 요소를 저장합니다.

import java.util.Collection;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("25", "10", "15", "20", "25");
        Collection<String> collection = stream.collect(Collectors.toCollection(TreeSet::new));
        System.out.println("Collection = " + collection);
    }
}

실행 결과

Collection = [10, 15, 20, 25]

중복된 값 "25"가 제거되고, 나머지 요소들이 오름차순으로 정렬되어 출력됩니다.

예제 2: counting()으로 요소 개수 세기

자바 스트림의 counting() 메서드를 사용하면 스트림에 포함된 요소의 개수를 손쉽게 구할 수 있습니다.

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Kevin", "Jofra", "Tom", "Chris", "Liam");
        // count
        long count = stream.collect(Collectors.counting());
        System.out.println("Number of elements in the stream = " + count);
    }
}

실행 결과

Number of elements in the stream = 5

이처럼 스트림 API를 활용하면 데이터의 필터링, 변환, 수집 과정을 메서드 체이닝으로 깔끔하게 표현할 수 있으며, 코드의 가독성과 유지보수성이 크게 향상됩니다.