본문으로 건너뛰기
Advertisement

스트림(Stream) 개요

자바 8부터 컬렉션(배열, List, Set, Map 등)의 요소를 하나씩 참조하며 함수형 인터페이스(람다식)를 적용해 반복적으로 처리할 수 있도록 해주는 스트림(Stream) 기능이 도입되었습니다.

스트림은 기존의 for문이나 Iterator를 사용하던 방식의 복잡성과 보일러플레이트 코드를 획기적으로 줄이고, 데이터를 데이터베이스 쿼리처럼 선언적으로 가공할 수 있게 해줍니다.

1. 스트림의 특징

  1. 원본 데이터를 변경하지 않음 (Read-only): 스트림은 데이터를 읽어서 가공할 뿐, 소스(원본) 데이터를 변경하지 않습니다.
  2. 일회용 (One-time use): 컬렉션의 요소를 순회하는 스트림은 한 번 사용하고 나면 닫히게 되어 재사용할 수 없습니다. 필요하다면 새로운 스트림을 다시 생성해야 합니다.
  3. 내부 반복 (Internal Iteration): 개발자가 직접 반복문(for, while)을 작성하는 외부 반복과 달리, 스트림은 내부에서 반복 처리가 이루어집니다. 이를 통해 코드가 매우 간결해집니다.

2. 스트림 파이프라인 (Stream Pipeline)

스트림 연산은 파이프에 물이 흐르는 것처럼 여러 단계를 거쳐 처리됩니다. 크게 스트림 생성, ** 중간 연산**, ** 최종 연산**의 세 단계로 나뉩니다.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

long count = names.stream() // 1. 스트림 생성
.filter(n -> n.length() > 3) // 2. 중간 연산 (조건 필터링)
.count(); // 3. 최종 연산 (개수 세기)

지연 연산 (Lazy Evaluation)

스트림의 가장 중요한 특징 중 하나는 최종 연산이 호출되기 전까지는 실제로 어떤 중간 연산도 수행되지 않는다 는 점입니다. 이를 '지연 연산(Lazy Evaluation)'이라고 합니다. 최종 연산이 호출될 때 비로소 데이터가 흐르기 시작하며, 이 덕분에 불필요한 메모리 소모를 막고 성능을 최적화할 수 있습니다.

3. 스트림 생성하기

컬렉션과 배열에서 스트림을 생성하는 기본 방식은 다음과 같습니다.

// 1. List/Set 등 Collection 인터페이스를 구현한 클래스에서
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> streamFromList = list.stream();

// 2. 배열에서
String[] arr = {"A", "B", "C"};
Stream<String> streamFromArray = Arrays.stream(arr);

// 3. 특정 범위의 숫자에서 (IntStream)
IntStream intStream = IntStream.rangeClosed(1, 10); // 1~10까지

다음 장에서는 스트림의 꽃이라고 할 수 있는 중간 연산(Intermediate Operations) 에 대해 알아보겠습니다.

Advertisement