🔎 Overview
자바를 공부하다보면, 스트림을 활용하는 코드들이 눈에 들어온다.
처음에는 무식하게 반복문을 돌리면서 하나하나씩 코딩하다가도, 스트림을 사용할 수 있게 되어 적용해보면 굉장히 깔끔하고 가독성 있는 코드를 작성할 수 있게 된다.
그렇다면 스트림이란 무엇이고, 언제 사용해야 하는 것일까?
스트림이란?
- 데이터의 흐름(데이터 스트림)을 추상화하여 함수형 프로그래밍 방식으로 데이터를 처리하게 도와주는 API
- 컬렉션, 배열 등의 데이터를 함수형 프로그래밍 방식으로 처리하기 위해 사용
- 스트림이라는 긴 파이프를 생성하고, 그 안에 있는 데이터를 하나씩 다룬다고 생각하면 편함
- for, while 등 반복문 대신 사용하며, 보다 깔끔하고 가독성 있는 코드를 작성할 수 있음
스트림의 구성
1. 스트림 생성
2. 중간 연산
- 값을 처리하기 위한 중간 연산을 수행
- 최종 연산이 없으면 실행되지 않으며, 값 또한 얻을 수 없음
- 이는 스트림이 일회성이기 때문
- 한 번 파이프에서 나오면, 다시 파이프로 들어가지 않는 한 파이프 안의 요소들을 다룰 수 없음
- 그러므로 이후 사용할 데이터라면, 파이프 내의 요소들을 잘 살펴본 뒤 값을 꼭 저장해주어야 함
📚 중간 연산의 종류
- filter(Predicate<? super T> predicate)
- predicate -> T와 상위 타입들을의 값을 인자로 받고, Boolean을 리턴
- 조건식을 통해 참인 것만 솎아냄
- map(Function<? super T, ? extends R> mapper)
- mapper -> T와 상위 타입들을 인자로 받고, R과 하위 타입으로 반환
- stream 내의 요소들을 각각 변환
- faltMap(Function<? super T,? extends Stream<? extends R>> mapper)
- T와 상위 타입들을 인자로 받고, R과 하위 타입들로 구성된 스트림으로 반환
- 입력된 요소에 대해 스트림을 생성하고, 이 스트림들을 하나의 스트림으로 결합
- 이차원 배열, 컬렉션 내 컬렉션 등, 하나의 스트림으로 연결하기 어려울 때 사용
- sorted() / sorted(Comparator<? super T> comparator)
- 정렬
- 기본적으로 오름차순
- comparator를 통해 정렬 방법 변경 가능
- distinct()
- limit(long n)
- skip(long n)
3. 최종 연산
- 스트림 결과를 반환하며, 스트림은 소모되어 사라짐
- 중간 연산 없이도 사용할 수 있으며, 중간 연산이 있을 시 중간 연산으로 나온 결과를 연산
🚩 최종 연산의 종류
- collect(Collector<? super T, A, R> collector)
- A는 중간 결과를 누적하는 객체의 타입
- 스트림 요소 처리 결과를 누적하여 저장
- T와 상위 타입들을 요소로 받고, 요소를 처리하고 누적하여 저장 후, R로 변환해서 반환
- 일반적으로 Collectors 클래스의 메서드로 생성
- ex) toList(), toSet(), groupingBy()...
- forEach()
- 스트림을 돌며 하나씩 소비
- 흔히 사용하는 반복문 개념
- reduce(BinaryOperator accumlator) ...
- 스트림의 각 요소를 누적하여 축소
- 두 T 값을 받아서 하나의 T값을 리턴하고, 이러한 연산을 반복 수행하여 그 값을 차례대로 누적
- count()
- allMatch()
- anyMatch()
- noneMatch()
- findFirst()
- 연산의 결과로 나온 첫번째 요소를 반환
- limit(1)과 동일
// 그 외에도 다양한 중간 및 최종 연산이 존재하며, 매개변수도 다양하게 올 수 있다.
🤔 그렇다면 언제 스트림을 사용하면 좋을까
1. 보다 가독성 있고 깔끔한 코드를 작성하고 싶을 때
- 반복문을 사용하면 대부분 코드가 길고 지저분해질 수 밖에 없는데, 스트림을 활용하면 몇 줄 이내에 깔끔하게 구현이 가능함
- 함수형 인터페이스를 통해 작성하기 때문에 가독성을 높여주고 유지보수 또한 쉽게 할 수 있음
2. 대량 데이터를 병렬 처리로 처리할 때
- 대량 데이터를 다룰 때 병렬 스트림을 활용하면, 멀티코어 CPU의 성능을 최대한 이용할 수 있음
3. 데이터를 한 번 쓰고 버릴 때
- 스트림은 재사용이 불가한 일회용
- 한 번 쓰고 버릴 데이터를 작업하기에 적합
참고) OpenAI. (2024).ChatGPT(4o)[Large language model].https://chatgpt.com/