<aside>
1️⃣ 자바 스트림(Stream)이란?
</aside>
- Stream은 자바에서 컬렉션 요소를 처리하는 기능을 제공하는 함수형 API이다. List로 선언된 객체의 요소에 대해 반복문을 돌리거나 데이터를 처리하기 위한 메서드들을 포함하고 있다. Stream을 사용하면 컬렉션의 요소에 대해 순차적으로 반복하며 원하는 작업을 수행할 수 있다. 이를 통해 반복문을 명시적으로 작성하지 않고도 간결하고 표현적인 코드를 작성할 수 있다.
- 예를 들어, List의 요소를 필터링하거나 매핑, 정렬, 그룹화, 집계 등의 작업을 Stream의 메서드를 사용하여 처리할 수 있다. 이러한 메서드들은 내부적으로 반복문을 수행하면서 작업을 처리한다.
- 또한 Stream을 사용하면 코드의 가독성을 높이고, 병렬 처리를 통해 성능을 향상시킬 수도 있다.
또한, Stream API는 함수형 프로그래밍 스타일을 적용할 수 있어 코드의 유지 보수성과 재사용성을 향상시킬 수 있다.
- 따라서, Stream은 List로 선언된 객체의 요소를 처리하기 위한 메서드들을 제공하는 함수형 API로 볼 수 있다.
<aside>
2️⃣ Stream은 어떤때에 사용되는가?
</aside>
- Stream은 다양한 상황에서 사용될 수 있다. 몇 가지 주요한 사용 사례를 살펴보면 다음과 같다.
- 컬렉션 데이터 처리
- Stream은 컬렉션 데이터를 처리하기 위한 편리하고 강력한 도구이다. 컬렉션의 요소를 필터링, 변환, 정렬, 그룹화 등 다양한 작업을 효율적으로 수행할 수 있다.
- 데이터 변환 및 가공
- Stream을 사용하여 데이터의 변환 작업을 수행할 수 있다. 예를 들어, 문자열 데이터를 파싱하여 숫자로 변환하거나, 객체의 특정 속성을 추출하여 새로운 컬렉션을 생성할 수 있다.
- 병렬 처리
- Stream은 병렬 처리를 지원한다. 멀티코어 프로세서의 성능을 최대한 활용하여 작업을 병렬로 처리할 수 있다. 이를 통해 대량의 데이터를 빠르게 처리할 수 있다.
- 함수형 프로그래밍
- Stream은 함수형 프로그래밍 스타일을 적용하기에 적합하다. 람다 표현식을 사용하여 간결하고 표현적인 코드를 작성할 수 있다. 또한, 스트림의 연산들은 함수형 프로그래밍에서 중요한 개념인 고차 함수를 활용한 조합성과 재사용성을 제공한다.
- I/O 작업 처리
- Stream은 파일 처리, 네트워크 통신 등의 I/O 작업에도 사용될 수 있다. InputStream이나 Reader 등의 I/O 클래스를 스트림으로 감싸서 데이터를 읽고 쓸 수 있다.
- 스트림은 데이터 처리를 간결하고 효율적으로 수행할 수 있는 강력한 도구이다. 함수형 프로그래밍 스타일을 지향하는 자바 개발자들에게 특히 유용하며, 코드의 가독성과 유지 보수성을 향상시킬 수 있다.
<aside>
3️⃣ Stream을 사용하는 경우의 장단점
</aside>
- Stream을 사용하는 경우의 장점
- 읽기 쉽고 유지보수가 쉽다
- Stream은 함수형 프로그래밍 스타일을 채택하여 데이터 처리 과정을 간결하고 가독성 좋게 표현할 수 있다.
- 병렬 처리를 효율적으로 수행할 수 있다
- Stream API는 쉽게 병렬처리를 할 수 있게 해준다. 이를 통해 멀티코어 프로세서의 이점을 활용할 수 있다.
- 연속된 데이터 처리를 체이닝할 수 있다
- Stream은 연속된 데이터 처리를 체이닝하여 표현할 수 있다. 이를 통해 중간 결과를 담을 변수가 필요 없어지므로 코드를 더욱 간결하게 만들 수 있다.
- 그러나 다음과 같은 경우에는 Stream 사용이 적절하지 않을 수 있다
- 성능 문제
- Stream API는 내부적으로 객체를 생성하고 사용하기 때문에 기본적인 반복문에 비해 오버헤드가 발생할 수 있다. 따라서 매우 큰 데이터셋을 다루거나 성능이 중요한 경우에는 일반적인 반복문을 사용하는 것이 더 효율적일 수 있다.
- 복잡한 로직
- 복잡한 로직이나 조건식은 Stream API를 사용하여 표현하면 오히려 코드가 복잡해지고 가독성이 떨어질 수 있다.
- 디버깅
- Stream API는 디버깅하기 어려울 수 있다. 특히 병렬 스트림의 경우 디버깅이 더욱 어렵다.
- 따라서, Stream API를 사용할지 여부는 사용하는 상황과 목표에 따라 결정해야 한다. 효율성, 가독성, 코드의 간결성 등을 고려하여 선택하는 것이 중요하다.
<aside>
4️⃣ Stream 사용 예시
</aside>
- 요소 필터링 및 매핑하기 (filter, map):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenSquares = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println(evenSquares); // [4, 16, 36, 64, 100]
- 위의 코드는
numbers
리스트에서 짝수를 필터링하고 각 짝수의 제곱 값을 새로운 리스트로 매핑하는 예시이다. filter
메서드로 짝수를 필터링하고, map
메서드로 각 요소의 제곱 값을 반환한다.
- 여기서 filter함수 안의 **
n
**은 numbers
리스트의 각 요소를 하나씩 가리키는 것이다.
- 리스트를 그룹화하기 (groupingBy):