BackEnd/Java

[Java] 스트림이란? 스트림의 사용이유와 컬렉션과 비교 예제

kangminhyuk1111 2024. 10. 20. 17:45

스트림이란? 스트림의 사용이유

Stream

자바 8 에서 추가된 Stream은 데이터 처리기능을 가지고 있으며, 데이터 처리 효율을 높여줍니다.

Stream의 사전적 의미는 ‘시냇물’이라는 의미를 가지며, 연속적인 사물이나 사람의 흐름 이라고 정의합니다.

Stream은 시간상에 나타나는 일련의 데이터 요소라고 정의함. 이는 데이터 집합의 의미보다는 연속적인 데이터의 흐름이라고 말하기 더 적합합니다.

결론적으로 Stream을 이용하면 일련의 데이터 처리 연산을 함수형 연산을 통해 표준화된 방법으로 쉽게 가공하고 처리할 수 있습니다.

Stream의 사용 이전에는 Collection으로 사용했었고 이는 코딩작업이 길어지며 가독성이 불편하여 작업할 때의 애로사항이 많았습니다.

하지만 Stream은 기존의 Collection처럼 명령형 방식으로 코딩하지 않고 무엇을 하고싶다. 라는 선언적 방식의 코딩이 가능합니다.

Stream vs Collection

Stream과 Collection은 데이터를 저장하고 처리하는 데에 사용됩니다.

하지만 역할과 사용 방식에서 큰 차이를 보입니다.

Collection은 데이터를 저장하는 컨테이너 입니다. Collection은 데이터를 메모리에 저장하고 추가 삭제 등 다양한 작업을 할 수 있도록 지원합니다.

하지만 Stream은 데이터를 저장하는 컨테이너가 아니라 데이터를 처리하는 추상화 입니다.
Collection, 배열 등 컨테이너의 정보를 가져와 일련의 흐름을 통해 데이터를 처리 가공하는 연속적인 데이터 흐름이며,
일회성으로 사용됩니다.

아래는 Stream과 Collection의 차이를 다룬 표입니다.

특성 Collection Stream
역할 데이터 저장 데이터 처리
크기 유한, 메모리 내 요소 유한 또는 무한
처리 방식 즉시 실행 지연 실행
변경 가능성 변경 가능 불변, 단일 사용
처리 모델 명시적 반복 처리 선언적 반복 처리, 내부 반복
병렬 처리 기본적으로 단일 스레드 병렬 처리 가능 (parallelStream 사용)

비슷하지만 서로다르며, 가장 중요한 점은 Stream은 최종 연산을 하기 전 까지는 실제로 수행되지 않으며, 이는 Stream이 데이터의 흐름이라는 의미이기도 합니다.

Stream 예제

실제로 Stream을 어떻게 사용할까요?

먼저 Collection을 사용해 리스트에 있는 모든 값을 제곱수로 반환하는 예시로 Collection과 Stream을 비교해 보겠습니다.

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
        List<Integer> squaredList = new ArrayList<>();

        for (Integer number : list) {
            squaredList.add(number * number);
        }

        System.out.println("squaredList = " + squaredList);
    }
}

위 코드는 컬렉션의 각각의 수에 제곱을 하여 새로운 리스트를 반환합니다.

이 코드는 몇가지 단점을 가지고 있습니다.

  • 명령형 스타일: for 루프를 사용하여 명령형 스타일로 작성되었습니다. 이는 직관적이지만, 가독성 측면에서 코드가 복잡해질 수 있습니다. 함수형 프로그래밍을 활용하면 더 간결하고 읽기 쉬운 코드를 작성할 수 있습니다.
  • 불필요한 가변성: squaredList는 새로운 값을 추가하는 방식으로 가변성을 가지고 있습니다. 가변성을 줄이면 코드의 안정성과 예측 가능성을 높일 수 있습니다.

Stream을 사용하면 다음과 같은 코드를 조금 더 효율적으로 변경이 가능합니다.

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
        List<Integer> squaredList = list.stream().map(number -> number * number).toList();

        System.out.println("squaredList = " + squaredList);
    }
}

위 코드는 컬렉션을 Stream을 통해 처리한 방식입니다.

선언형 스타일을 통해 가독성이 높아지고, 각 작업을 명확하게 단계별로 나타내기 냅니다.

아래 링크는 Stream연습을 위한 문제 100선입니다. 풀면 도움이 될 것 같습니다.

https://github.com/gywns0417/java-stream-practice

반응형