이전까지는 스트림을 외부반복에서 내부반복으로 바꾸는 방법을 보았다. filter, collect 연산을 지원하는 스트림 API를 이용해서 내부처리를 하자.
List<Dish> vegitarianDishes = menu.stream().filter(Dish::isVegitarain).collect(toList());
요컨대 스트림은 "데이터는 내가 처리할게, 관련작업은 누가 할래?" 가 된 것이다.
이제는 그럼 스트림이 지원하는 연산으로 필터링, 슬라이싱, 매핑, 검색, 매칭, 리듀싱 등 데이터 처리 질의를 공부해보자.
stream 인터페이스는 filter 메서드를 지원하는데, 이는 boolean을 반환하는 함수
인 프레디케이트를 인수로 받아 이와 일치하는 요소를 스트림으로 다시 반환한다.
예를 들어보자.
// 채식 요리인지 확인하는 메서드 참조
List<Dish> vegetarianMenu = menu.stream().filter(Dish::isVegitarian).collect(toList());
스트림은 고유 요소로 이루어진 스트림을 반환하는 distinct 메서드도 지원한다.
예) list에 있는 모든 짝수를 선택하고 중복을 필터링해라.
List<Integer> numbers = Arrays.asList(1,2,1,3,3,2,4);
numbers.stream().filter(i -> i%2 == 0).distinct().forEach(System.out:println);
Stream에서 숫자 스트림을 생성하고, filter로 짝수만 거르면 2, 2,4만 남으며 distinct()를 거치면서 중복된 2가 하나만 남게 된다.
앞서서 설명했던 프레디케이트를 이용해서도 스트림의 요소를 선택 및 스킵을 할 수 있다. takeWhile, dropWhile이 이에 해당한다.
List<Dish> filterMenu = specialMenu.stream().filter(dish->dish.getCalories() < 320).collect(toList());
위 리스트에서는 칼로리 순으로 정렬이 되어있으므로, 이미 filter을 통해 프레디케이트가 적용된다. 그러면 이 사실을 이용해 320 칼로리보다 크거나 같을 때는 반복을 중단할 수 있다.
filter을 takeWhile로만 바꿔주면 된다.
dropWhile은 320 칼로리보다 큰 요소를 탐색할 때 사용한다. takewhile과 정 반대를 수행하는데, 프레디케이트가 거짓
이 되는 지점까지 발견된 요소를 버린다. 그래서 거짓이 되는 시점에서 작업을 중단하고 남은 요소를 반환하게 된다.