스트림 vs 시퀀스

권민주·2025년 6월 28일

코틀린

목록 보기
6/12
post-thumbnail

1. Stream

1)개념

  • Java 8부터 추가된 기술로 일련의 데이터의 흐름에 람다를 이용하여 함수형 연산을 지원하는 클래스
  • 복잡한 반복문과 조건문 대신 표준화된 방식으로 간결하게 데이터 처리

2)특징

  • 병렬처리 지원
    • 데이터의 흐름을 나누어서 멀티 스레드를 통해 병렬로 처리
    • parallel() 또는 parallelStream()으로 병렬처리 가능
    • 데이터 처리 후 합치기 때문에 대량의 데이터를 빠르고 쉽게 처리
  • 생성, 가공, 소비 구조
    • 생성에서는 데이터가 필요할 때만 메모리에 로드. 불필요한 데이터를 로드하지 않아도 되어 효율적
    • 가공은 데이터를 원하는 형태로 변형. 결과물이 Stream이기에 중간 연산을 연결하여 여러 번 수행 가능
    • 소비는 Stream에 대한 최종 연산을 수행. 컬렉션이나 하나의 값으로 반환
    • 최종 연산은 결과물을 얻기 위한 목적으로 1번만 수행. Stream이 닫혀서 더 이상 중간 연산이나 최종 연산 불가능. 중간 연산들은 연산을 호출할 때 즉시 수행되지 않고, 최종 연산이 호출될 때까지 지연. 이를 Lazy Evaluation(지연 평가)

참고
https://www.elancer.co.kr/blog/detail/255

2. Sequence

1)개념

  • 요소의 크기를 나중에 결정할 수 있는 순차적인 컬렉션
  • 중간 처리 없이 마지막 메소드 때 모든 연산 계산 처리

2)특징

  • 메모리나 속도 줄어줌
    • map 같이 새로운 컬렉션을 반환하는 메소드들을 연속적으로 연결하여 사용하면 각 메소드가 끝날 때 마다 새로운 컬렉션을 생성.
    • 한 메소드가 반환한 컬렉션을 다음 메소드로 전달하는 형태. 이런 형태는 메모리나 속도 낭비를 야기하기에 이를 해결해주는 병렬 처리 asSequence() 사용
  • 크기가 작은 컬렉션에 주의
    • filter()같은 함수는 인라인으로 실행되기에 큰 부담이 되지 않음.
    • 시퀀스를 사용하면 한 번 계산된 연산은 람다식을 저장하는 객체로 표현되며 중간 결과가 메모리에 저장됨. 이는 인라인 함수에 최적화 되지 않으며(인라인되지 않음) 불필요한 메모리 사용 증가.
    • 시퀀스를 인자로 넘기면 람다 저장하는 객체가 추가로 필요

3. Stream vs Sequence

1)비교

특징자바 스트림 (Stream)코틀린 시퀀스 (Sequence)
언어와 플랫폼자바 8+의 표준 라이브러리코틀린에 최적화된 API
구현 방식자바 컬렉션과 배열에서 작동Sequence 인터페이스는 코틀린 컬렉션과 연관
상태 여부소모형으로 재사용 불가능상태 없음 (재사용 가능)
기본 자료형 지원기본 자료형용 스트림 제공
(IntStream, DoubleStream 등)
일반 시퀀스 (Sequence) 사용
동작 방식파이프라인 전체가 최종 연산 시 한꺼번에
평가. 중간 연산들은 지연되며, 최종 연산이 호출될 때 전체 흐름이 실행
단일 항목 단위로 지연 평가. 하나의 항목이 다음
연산으로 바로 전달되고 처리. 연산이 체이닝 되어 있어도 항목 하나씩 순차적으로 진행
멀티스레딩 지원병렬 스트림(parallelStream())으로 멀티스레딩 가능시퀀스 자체는 멀티스레딩을 지원하지 않음
최종 연산
결과
컬렉션, 단일 값, 또는 특화된 스트림
결과 반환
컬렉션 또는 단일 값으로 변환 가능
호환성코틀린 컬렉션과 호환하려면 변환필요자바 컬렉션과도 호환 가능

2)예시 코드

  • 스트림
numbers.stream()
    .map(n -> {
        System.out.println("map: " + n);
        return n * 2;
    })
    .filter(n -> {
        System.out.println("filter: " + n);
        return n > 2;
    })
    .forEach(n -> System.out.println("result: " + n));
/*
map: 1
map: 2
map: 3
filter: 2
filter: 4
filter: 6
result: 4
result: 6

모든 map 수행 후 모든 filter 수행
*/

-시퀀스

numbers.asSequence()
    .map {
        println("map: $it")
        it * 2
    }
    .filter {
        println("filter: $it")
        it > 2
    }
    .forEach {
        println("result: $it")
    }

/*
map: 1
filter: 2
map: 2
filter: 4
result: 4
map: 3
filter: 6
result: 6

각 항목 단위로 실행
*/
profile
안드로이드 개발자:D

0개의 댓글