김지팡의 저장소
Published 2024. 11. 24. 17:41
Stream API 이해하기 TIL
728x90

 

이번 포스팅에서는 Stream API에 대해서 이야기해보고자 한다.

 

 

📌 Stream이 무엇일까?

 

스트림은 데이터의 연속된 흐름을 이야기하는데, 연속된 데이터에 대해 어떠한 연산을 수행시키기 위한 인터페이스이다.

연속된 데이터에 대해 연산을 수행시키는 것이기 때문에 리스트, 맵, 배열 같은 데이터 컬렉션을 처리할 때 사용된다.

 

 

📌 Stream은 어떤 연산들을 수행할까?

 

스트림은 연속된 데이터를 필터링, 매핑, 정렬, 집계 등의 연산을 수행한다.

 

스트림에는 중간 연산과 종료 연산이 있고, 이들은 각각 다른 역할들을 맡고 있다.

 

💡 중간 연산이 수행하는 역할


스트림을 변환해서 새로운 스트림으로 반환하는 역할을 한다. 그 역할에는 filter(), map(), sorted(), limit() 등 여러 가지가 있다.

 

예를 들어, 문자열로 이루어진 리스트가 있을 때, 그 리스트를 스트림으로 만들어 filter를 하든 map을 통해 데이터를 변환하든 등의 동작을 수행시키도록 할 수 있다.

 

이러한 리스트에게 연산을 수행시킨 후, 종료 연산이 연산을 하도록 넘긴다. 또한, 중간 연산은 여러 개 엮어 사용이 가능하다.

 

💡 종료 연산이 수행하는 역할


중간 연산의 결과(스트림)를 받아 종료 연산을 수행한다. forEach(), collect(), count() 등의 연산을 수행한다.

 

예시로, 중간 연산의 결과 스트림으로 forEach()를 이용해 모든 요소를 출력하거나, collect()를 통해 다른 컬렉션 형태로 변환할 수 있다.

중간 연산과 종료 연산이 가지는 각각의 특징이 있다.

 

 

📌 연산의 특징에 대해 알아봅시다

 

💡 중간 연산이 가지는 특징


중간 연산은 최종 연산이 호출되기 전에는 실행되지 않는다. 이를 Lazy Evaluation이라고 하는데, 이는 코드로 보면 이해하기 쉽다.

import java.util.stream.Stream;

public class LazyEvaluationExample {
    public static void main(String[] args) {
        System.out.println("Stream 생성");

        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5)
            .filter(n -> {
                System.out.println("filter() 호출: " + n);
                return n % 2 == 0;
            })
            .map(n -> {
                System.out.println("map() 호출: " + n);
                return n * 2;
            });

        System.out.println("최종 연산 이전에는 아무 작업도 수행되지 않음");

        System.out.println("최종 연산 호출");
        stream.forEach(n -> System.out.println("최종 처리: " + n));
    }
}

// 출력 결과
/*

Stream 생성
최종 연산 이전에는 아무 작업도 수행되지 않음
최종 연산 호출
filter() 호출: 1
filter() 호출: 2
map() 호출: 2
최종 처리: 4
filter() 호출: 3
filter() 호출: 4
map() 호출: 4
최종 처리: 8
filter() 호출: 5

*/

위처럼 종료 연산인 forEach() 메서드가 실행되기 전에는 중간 연산이 호출이 안 된 것을 확인할 수 있다.

 

다시 말하면, 종료 연산이 호출되지 않으면 스트림 연산이 실행되지 않기 때문에 종료 연산은 필수적이라 말할 수 있다.

 

또한, 중간 연산 없이 종료 연산만으로 스트림을 구성할 수 있는데, 이를 스트림 파이프라인을 구성한다고 말한다. 스트림 파이프라인은 중간 연산이나 종료 연산을 연결해 실행하는 구조를 말한다.

 

 

📌 스트림의 내부 동작 방식에 대해 알아봅시다

 

스트림은 중간 연산과 종료 연산을 사용해 스트림 파이프라인을 구성할 수 있다.

 

구성된 파이프라인 중 스트림 내부적으로 중간 연산들을 기록한다. 스트림 API는 종료 연산이 호출되기 전까지 중간 연산이 실행되지 않기 때문이다.

 

중간 연산의 실행 계획을 기록하여 종료 연산이 실행됐을 때 중간 연산들을 수행한다.

 

 

📌 마무리

 

Stream API를 잘 다루지 못하기도 하고, 내부적으로 어떻게 동작하는지를 몰랐었다.

 

이번 포스팅을 작성하기 위해 학습해 보면서 더 깊이 이해할 수 있었다. 특히 내부적으로 Stream API가 어떻게 동작하는지를 학습하니 이미 작성된 것을 이해하는 것에도 수월하였고, 스스로도 더 잘 활용할 수 있게 되었다.

 

앞으로는 연습 삼아 과하게 사용해 볼 생각이다.

 

이번 학습을 통해 Stream API를 사용하는 가장 큰 장점은 가독성이라고 생각했다.

 

무조건 가독성이 좋아지는 것은 아니지만, 함수형 프로그래밍 기법으로서 어떠한 연산을 수행시킬 것인지를 한눈에 보여주기 때문에 가독성을 보장하는 것은 맞다고 생각한다.

728x90

'TIL' 카테고리의 다른 글

Subnet 이해하기  (0) 2024.12.21
VPC 이해하기  (1) 2024.12.14
가변 객체(Mutable)와 불변 객체(Immutable)  (0) 2024.11.21
ORM과 JPA 이해하기  (6) 2024.11.14
Set 이해하기  (0) 2024.11.08
profile

김지팡의 저장소

@김지팡

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!