-
서론
자바 8에서 추가된 스트림은 무엇인지 컬렉션과 무엇이 다른지 등 스트림의 대해서 설명
스트림이란?
Java 8 API에 새로 추가된 기능으로 스트림을 이용하면 선언형(데이터를 처리하는 임시 구현 코드 대신 질의로 표현)으로 컬렉션 데이터를 처리할 수 있다. 또한 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다.
특징으로는 선언형(간결 및 가독성 증가), 조립가능(유연성 증가), 병렬화(성능 증가) 가 존재한다.
(스트림은 계속해서 챕터에 나오므로 순차적으로 배워가면 된다.)
스트림 == 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소
-
요소의 정의
-
연속된 요소
-
컬렉션과 동일하게 스트림은 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스를 제공한다. 컬렉션은 자료구조이기에 시간과 공간의 복잡성과 고나련된 요소 저장 및 접근 연산이 주를 이룬다. 반면 스트림은 filter, sorted, map처럼 표현 계산식을 주로 이룬다.
-
-
소스
-
스트림은 컬렉션, 배열, I/O 자원 등 데이터 제공 소스로부터 데이터를 소비한다. 정렬된 컬렉션으로 스트림을 생성하면 정렬이 그대로 유지된다
-
-
데이터 처리 연산
-
스트림은 함수형 프로그래밍 언어에서 지원하는 연산과 DB와 비슷한 연산을 지원하며, 스트림 연산은 순차적, 병렬로 실행이 가능하다.
-
-
-
스트림 특징
-
파이프라이닝
-
스트림 연산은 스트림 연산끼리 연결해서 커다란 파이프라인을 구성할 수 있도록 스트림 자신을 반환한다. 그 덕분에 게으름(아래에 설명 예정), 쇼트서킷(설명 예정) 같은 최적화도 얻을 수 있으며, 연산 파이프라인은 데이터소스에 적용하는 데이터베이스 질의와 비슷하다.
-
-
내부 반복
-
반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 내부반복을 지원한다.(아래에 설명 예정)
-
-
스트림과 컬렉션 차이
-
컬렉션
-
현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료구조로 모든 요소는 컬렉션에 추가하기 전에 계산이 되어 있어야한다.(추가 및 삭제의 연산을 수행할 때마다 컬렉션의 모든 요소를 메모리에 저장해야 하며, 컬렉션에 추가하려는 요소는 미리 계산이 되어있어야 한다.)
-
-
스트림
-
스트림은 이론적으로는 요청할 때만 요소를 계산하는 고정된 자료구조이다. 이러한 특성으로 스트림은 사용자가 요청하는 값만 스트림에서 추출하는게 핵심이다. 물론 사용자는 이러한 변화를 알 수 없어 결국에는 생성자, 소비자 관계를 형성한다. 또한 스트림은 게으르게 만들어지는 컬렉션과 같다.(게으름) 사용자가 데이터를 요청할 때만 값을 계산하여 요청 중심제도 및 즉석 제조라고 불리기도 한다.
-
스트림의 소비
스트림 또한 반복자와 마찬가지로 한번만 탐색이 가능하며, 탐색된 스트림의 요소는 소비되어 사용할 수 없으므로 새로운 스트림을 생성해야 한다.
List<String> titleList = Arrays.asList("java", "title", "8", "action"); Stream<String> streamExam = titleList.stream(); // java, title, 8, action 출력 streamExam.forEach(System.out::println); // IllegalStateException 발생 streamExam.forEach(System.out::println);
외부 반복 내부 반복
컬렉션 인터페이스를 사용하려면 사용자가 직접 요소를 반복해야 하는데 이를 외부 반복이라고 한다. 반면 스트림 라이브러리는 반복을 알아서 처리하고 결과 스트림값을 어딘가에 저장해주는 내부 반복을 사용한다.
하나의 작업이 종료 시 다음 작업을 명시적으로 처리해주어야 하는 외부 반복과 달리 내부 반복은 명시적으로 처리를 지정해주지 않아도 투명하게 병렬로 처리하거나 더 최적화된 다양한 순서로 처리할 수 있다.
더보기외부/내부 반복 차이점 예제소피아에게 인형을 정리하라고 말하는 상황
나 : 소피아, 장남감 좀 정리하렴. 방바닥에 장난감 있지?
소피아 : 네 공이 있어요.
나 : 그럼 공을 상자에 담자. 또 어떤 장난감이 있지?
소피아 : 인형이 있어요.
나 : 그럼 인형을 상자에 담자. 또 어떤 장난감이 있지?
소피아 : 책이 있어요.
나 : 그럼 책을 상자에 담자. 또 어떤 장난감이 있지?
소피아 : 아무것도 없어요.
나 : 참 잘했어.
스트림 연산
스트림의 연산은 중간 연산, 최종 연산으로 구분지을 수 있다.
List<String> calExam = menu.stream() .filter(dish -> dish.getCalories() > 150) // 중간 연산 .map(Dish::getName) // 중간 연산 .limit(2) // 중간 연산 .collect(Collectors.toList()); // 최종 연신
중간 연산은 다른 스트림을 반환한다. 따라서 여러 중간 연산을 연결해 질의를 할 수 있으며, 단말 연산을 스트림 파이프라인에 실행하기 전까지 아무 연산을 수행하지 않는다.(게으름)추후 중간 연산을 합친 다음 최종 연산으로 한 번에 처리한다. 이러한 게으름 특성으로 filter, map등 서로 다른 연산을 병합하여 루프 퓨전을 할 수 있다.
최종 연산은 스트림 파이프라인에서 결과를 도출하며, List, Integer, void 등 스트림 이외에 결과가 반환된다.
스트림 이용 결론
- 질의를 수행할 데이터 소스
- 스트림 파이프라인을 구성할 중간 연산 연결
- 스트림 파이프라인을 실행하고 결과를 만들 최종 연산
그나마 git : github.com/hodolee246/ModernJavaStudygithub.com/hodolee246/ModernJavaStudy/blob/master/src/main/java/com/example/modernjava/ch4/StreamExam.java
'모던자바인액션' 카테고리의 다른 글
챕터[7] 스트림 병렬화 (0) 2020.10.21 챕터[6] 스트림 그룹화 (0) 2020.10.21 챕터[5] 스트림 데이터 수집 (0) 2020.10.21 챕터[3] 람다 (0) 2020.10.21 챕터[2] 동작 파라미터화 (0) 2020.10.21 -