본문 바로가기

JAVA

[Java] 스트림(Stream)

 

 

Stream(Stream)

데이터를 효율적이고 선언적으로 처리할 수 있게 해주는 API이다. 컬렉션(List, Set 등)의 데이터를 필터링, 매핑, 정렬 등의 작업을 함수형 프로그래밍(순수 함수를 조합하고 소프트웨어를 만드는 방식) 스타일로 처리할 수 있게 도와준다. 쉽게 말해서, 데이터를 효율적으로 흐름에 맞추어 처리한다는 의미이다.

 


 

스트림의 특징

  • 스트림은 데이터를 저장하지 않는다.
  • 원본 데이터를 변경하지 않는다. (불변성 유지)
  • 스트림은 컬렉션(List, Set 등)과 함께 자주 활용된다.
  • 생성 → 중간 연산(Intermediate Operation) → 최종 연산(Terminal Operation) 순으로 처리 된다. (선언형 스타일)
  • 지연 연산(Lazy Evaluation)을 사용하여 최종 연산이 수행될 때까지 중간 연산이 실제로 실행되지 않는다.

 


 

스트림의 구성 요소

1. 생성 (Stream 생성)

List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = list.stream();

 

2. 중간 연산 (Intermediate Operation)

stream.filter(s -> s.length() > 5);
  • 스트림을 변형하거나 필터링한다.
  • 예: filter(), map(), sorted(), distinct() 등

3. 최종 연산 (Terminal Operation)

long count = list.stream()
                 .filter(s -> s.length() > 5)
                 .count();
  • 결과를 도출하고 스트림을 종료한다.
  • 예: forEach(), collect(), count(), reduce() 등

 


 

 

스트림 단계에 따른 주요 메서드 정리

단계 메서드 설명
1. 데이터 준비 stream() 데이터를 스트림으로 변환
parallelStream() 데이터를 스트림으로 변환(병렬 처리, 멀티 스레드)
2. 중간 연산 등록
(즉시 실행되지 않는다.)
filter(Predicate) 조건에 맞는 요소만 필터링
map(Function) 요소를 다른 형태로 매핑 (예: 대문자로 변환)
sorted() 정렬
distinct() 중복 제거
limit(n) 앞에서부터 n개 요소 제한
3. 최종 연산 collect() 스트림 결과를 리스트나 집합 등으로 수집
reduce() 모든 요소를 하나로 합침
forEach() 각 요소에 대해 동작 수행
count() 총 요소 갯수 반환

 

 


 

 

비교해보기 (for vs 스트림)

각 요소를 10배로 변환 후 출력하는 예시로 알아봅시다.

  • ArrayList의 각 요소는 10배로 변환한다.
  • 아래 예시를 보고 for 문과 스트림을 비교해보자.
더보기
import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>(List.of(1, 2, 3, 4, 5));

        // for 명령형 스타일 : 각 요소 * 10 처리
        ArrayList<Object> result1 = new ArrayList<>();
        for (Integer num : arrayList) {
            Integer nultipliedNum = num * 10;
            result1.add(nultipliedNum);
        }
        System.out.println("result1 = " + result1);

        // stream 선언형 스타일: 각 요소 * 10 처리
        List<Integer>result2 = arrayList.stream()      // 1. 데이터 흐름 준비
                .map(num -> num * 10)                  // 2. 중간 연산 등록
                .collect(Collectors.toList());         // 3. 최종 연산 단계
        System.out.println("result2 = " + result2);
    }
}

for문은 5줄에 걸쳐서 진행되었지만, stream을 사용하여 한 줄로 가능하게 되었다.

 

콘솔

 

 


 

 

익명 클래스와 람다를 스트림에서 활용

다음 코드에서 map 매개 변수에서 람다 식이 활용되었다. 어떻게 활용할 수 있었는지 뜯어보자.

List<Integer>result2 = arrayList.stream()       // 1. 데이터 흐름 준비
        .map(num -> num * 10)                   // 2. 중간 연산 등록
        .collect(Collectors.toList());          // 3. 최종 연산 단계
System.out.println("result2 = " + result2);

우선 익명 클래스와 람다를 활용하려면, map 매개변수의 인터페이스가 추상 메서드를 하나만 가지고 있어야 한다.

 

 

map 메서드 구조

 

Function 함수용 인터페이스 구조

map 매개 변수인 mapper의 인터페이스를 확인해보니 함수형 인터페이스이다.

함수형 인터페이스는 추상 메서드가 하나이므로, 익명 클래스와 람다를 사용할 수 있다.

 

 

 

사용되는 과정

더보기

1. 익명 클래스를 직접 만들어서 변수에 담아 매개 변수로 전달하는 방법

Function<Integer, Integer> function = new Function<>() {

    @Override
    public Integer apply(Integer integer) {
        return integer * 10;
    }
};

List<Integer>result3 = arrayList.stream()       // 1. 데이터 흐름 준비
        .map(function)                          // 2. 중간 연산 등록
        .collect(Collectors.toList());          // 3. 최종 연산 단계
System.out.println("result3 = " + result3);

 

2.  람다식을 만들어서 변수에 담아 매개변수로 전달

Function<Integer, Integer> functionalLambda = (interger -> interger * 10);

List<Integer>result4 = arrayList.stream()       // 1. 데이터 흐름 준비
        .map(functionalLambda)                  // 2. 중간 연산 등록
        .collect(Collectors.toList());          // 3. 최종 연산 단계
System.out.println("result4 = " + result4);

 

3. 람다식을 직접 매개변수로 전다

// 3. 람다식을 직접 매개변수로 전달
List<Integer>result5 = arrayList.stream()       // 1. 데이터 흐름 준비
        .map(num -> num * 10)                   // 2. 중간 연산 등록
        .collect(Collectors.toList());          // 3. 최종 연산 단계
System.out.println("result5 = " + result5);

 

 

 

 

https://kimyongjun0129.tistory.com/106

 

[Java] 람다(Lamda)란?

람다(Lamda)익명 클래스를 간단하게 표현하는 방식이다. 즉, 익명 클래스의 메서드를 코드 블록으로 만들어서 변수에 넘기거나 인자로 전달 할 수 있게 해주는 기능이다. 람다 문법Calculator c = (a, b

kimyongjun0129.tistory.com

 

'JAVA' 카테고리의 다른 글

[Java] Lv_2 계산기 프로젝트  (0) 2025.04.18
[Java] Lv_1 계산기 프로젝트  (0) 2025.04.17
[Java] 익명 클래스란?  (0) 2025.04.17
[Java] 람다(Lamda)  (0) 2025.04.17
[Java] 추상 클래스(abstract class)란?  (0) 2025.04.16