스트림 소개
컬렉션은 자바에서 가장 많이 사용하는 기능 중 하나
스트림이란?
스트림은 자바 API에 새로 추가된 기능,스트림을 이용하면 선언형(즉,데이터를 처리하는 임시 구현 코드 대신 질의로 표현가능함) => 컬렉션 데이터를 처리함
스트림 -> 데이터 컬렉션 반복을 처리하는 기능
스트림 이용하면 멀티스레드 코드를 구현 안해도 데이터를 투명하게 병렬로 처리가능
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; List<String> lowCaloricDishesName = menu.stream() .filter(d -> d.getCalories() < 400) //400 칼로리 이하의 요리 선택 .sorted(comparing(Dish::getCalories)) //칼로리로 요리 정렬 .map(Dish::getName) //요리명 추출 .collect(toList()); //모든 요리명을 리스트에 저장 stream() -> parallelStream()으로 바꾸면 멀티코어 아키텍처에서 병렬로 실행 가능함 import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; List<String> lowCaloricDishesName = menu.parallelStream() .filter(d -> d.getCalories() < 400) //400 칼로리 이하의 요리 선택 .sorted(comparing(Dish::getCalories)) //칼로리로 요리 정렬 .map(Dish::getName) //요리명 추출 .collect(toList()); //모든 요리명을 리스트에 저장 | cs |
자바 8의 스트림 API의 특징
선언형 : 더 간결하고 가독성 좋아짐
조립할 수 있음 : 유연성이 좋음
병렬화 : 성능이 좋아짐
스트림? '데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소로 정의'
파이프라인 = 소스에 적용하는 질의 같은 존재
filter : 람다를 인수로 받아 스트림에서 특정 요소를 제외시킨다
map : 람다를 이용해서 한 요소를 다른 요소로 변환하거나 정보를 추출
limit : 정해진 개수 이상의 요소가 스트림에 저장되지 못하게 스트림 크기를 축소
collect : 스트림을 다른 형식으로 변환
컬렉션과 스트림의 가장 큰차이
컬렉션은 현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료구조
컬렉션의 모든 요소는 컬렉션에 추가하기 전에 계싼되어야 함
스트림은 요청할 때만 요소를 계산하는 자료구조(스트림에 요소를 추가하거나 스트림에서 요소를 제거할수 없음)
스트림도 한번만 탐색가능 (탐색된 스트림의 요소는 소비됨)
1 2 3 4 | List<String> title = Arrays.asList("Java8", "In", "Action"); Stream<String> s = title.stream(); s.forEach(System.out::println); // title의 각 단어 출력 s.forEach(System.out::println); //스트림이 이미 소비되었거나 | cs |
스트림은 단 한번만 소비할 수 있음
컬렉션과 스트림의 또 다른 차이점 데이터 반복 처리 방법
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //외부반복 (for-each) List<String> names = new ArrayList<>(); for(Dish d: menu) { //명시적 순차 반복 names.add(d.getName()); //이름 추출 리스트에 추가 } List<String> names = new ArrayList<>(); Iterator<String> iterator = menu.iterator(); while(iterator.hasNext()) { Dish d = iterator.next(); names.add(d.getName()); } //내부반복(반복을 알아서 처리하고 결과 스트림값을 어딘가에 저장) List<String> names = menu.stream() .map(Dish::getName) //map 메서드 getName 메서드로 파라미터화해서 요리명 추출 .collect(toList()); //파이프라인 실행 반복자 필요 X | cs |
연결할 수 있는 스트림 연산 중간 연산(filter,map,limit)
스트림을 닫는 연산을 최종 연산(collect)
스트림 이용하기 요약
-질의를 수행할 (컬렉션 같은) 데이터 소스
-스트림 파이프라인을 구성할 중간 연산 연결
-스트림 파이프라인을 실행하고 만들 최종 연산
중간 연산
연산 |
형식 |
반환 형식 |
연산의 인수 |
함수 디스크립터 |
filter |
중간 연산 |
Stream<T> |
Predicate<T> |
T -> boolean |
map |
중간 연산 |
Stream<T> |
Function<T, R> |
T -> R |
limit |
중간 연산 |
Stream<T> |
|
|
sorted |
중간 연산 |
Stream<T> |
Comparator<T> |
(T, T) -> int |
distinct |
중간 연산 |
Stream<T> |
|
|
최종 연산
연산 |
형식 |
목적 |
forEach |
최종 연산 |
스트림의 각 요소를 소비하면서 람다를 적용 void 반환 |
count |
최종 연산 |
스트림의 요소 개수를 반환한다.long을 반환한다. |
collect |
최종 연산 |
스트림을 리듀스해서 리스트,맵,정수 형식의 컬렉션을 만듬 |
요약
스트림은 소스에서 추출된 요소로 데이터 처리 연산을 지원함
스트림은 내부 반복을 지원함,내부 반복은 filter,map,sorted 등의 연산으로 반복을 추상화
스트림에는 중간 연산과 최종 연산이 있음
filter와 map처럼 스트림을 반환하면 다른 연산과 연결될 수 있는 연산을 중간연산
중간연산을 이용해서 파이프라인을 구성가능 -> 중간연산으로 어떤 결과도 생성 못함
forEach와 count처럼 스트림 파이프라인을 처리해서 스트림이 아닌 결과를 반환하는 연산을 최종 연산
스트림의 요소는 요청할 때만 계산
댓글