filter 메서드
distinct 메서드
List<Integers> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
스트림의 요소를 효과적으로 선택할 수 있도록 takeWhile, dropWhile 지원함
이미 정렬된 리스트에서는 필터링보다는 takeWhile 함수를 쓰는 것이 효율적임
List<Dish> slicedMenu = specialMenu.stream()
.takeWhile(dish -> dish.getCalories() < 320)
.collect(toList());
takeWhile과 정반대의 작업 수행limit(n) 메서드: 최대 요소 n개 반환
skip(n): n개의 요소를 건너뜀
map
List<String> dishnames = menu.stream()
.map(Dish::getName)
.collect(toList())
flatMap 메서드: 하나의 평면화된 스트림 반환
List<String> uniqueCharacters =
words.stream()
.map(word -> word.split("")) // 각 단어를 개별 문자를 포함하는 배열로 반환
.flatMap(Arrays::stream) // 생성된 스트림을 하나의 스트림으로 평면화
.distinct()
.collect(toList());
anyMatch: predicate이 주어진 스트림에서 적어도 한 요소와 일치하는지 확인
if (menu.stream().anyMatch(Dish::isVegan)) {
System.out.println("The menu is vegan friendly");
}
allMatch: predicate이 스트림의 모든 요소와 일치하는지
boolean isHealthy = menu.stream()
.allMatch(dish -> dish.getCalories() < 1000);
noneMatch: 주어진 predicate와 일치하는 요소가 없는지 확인
allMatch와 반대 연산boolean isHealthy = menu.stream()
.noneMatch(d -> d.getCalories() >= 1000);
anyMatch, allMatch, noneMatch는 스트림 쇼트서킷 기법을 사용한다
&&, ||와 같은 연산limit또한 쇼트서킷findAny: 현재 스트림에서 임의의 요소를 반환
filter와 함께 쓰이면 유용Optional<Dish> dish = menu.stream()
.filter(Dish::isVegan)
.findAny();
Optional: 값의 존재/부재 여부를 표현하는 컨테이너 클래스
findAny는 아무 요소도 반환하지 않을 수 있는데 null은 에러가 일어나기 쉬우므로 Optional 사용isPresent(): Optional이 값을 포함하면 trueOptional이 값을 포함하지 않으면 falseifPresent(Consumer<T> block): 값이 있으면 주어진 블록 실행T get(): NoSuchElementException 일으킴T orElse(T other)findFirst vs. findAny
findAny 사용Optional<Dish> dish = menu.stream()
.filter(Dish::isVegan)
.findFirst();
리듀싱 연산: 모든 스트림 요소를 처리해서 값으로 도출하기
reduce를 실행할 수 있게 됨sum 변수를 공유해야하므로 병렬화가 어려움reduce는 parallelStream() 사용하면 됨초기값은 0인 상태에서 요소의 합
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
메서드 참조로 더 간단히 하면
int sum = numbers.stream().reduce(0, Integer::sum);
초기값은 1인 상태에서 요소의 곱
int product = numbers.stream().reduce(1, (a, b) -> a * b);
초기값 없는 reduce는 Optional을 반환함
Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b);
reduce 연산은 새로운 값을 이용해 스트림의 모든 요소를 소비할 때까지 람다를 반복 수행하면서 최댓(최솟)값을 생산함
Optional<Integer> max = numbers.stream().reduce(Integer::max);
Optional<Integer> min = numbers.stream().reduce(Integer::min);
transactions.stream()
.filter(t -> t.getYear == 2011)
.sorted(comparing(Transaction::getValue))
.collect(toList());
transactions.stream()
.map(t -> t.getTrader().getCity())
.distinct()
.collect(toList());
transactions.stream()
.map(t -> t.getTrader())
.filter(t -> t.getCity().equals("Cambridge"))
.sorted(comparing(Trader::getName))
.collect(toSet());
transactions.stream()
.map(t -> t.getTrader().getName())
.distinct()
.sorted()
.collect(joining());
joining: 내부적으로 StringBuilder를 이용해 모든 문자열을 반복적으로 연결해 새로운 문자열 객체를 만듬transactions.stream()
.filter(t -> t.getTrader().getCity().equals("Milan")
.findAny();
transactions.stream()
.filter(t -> t.getTrader().getCity.equals("Cambridge")
.map(Transaction::getValue)
.distinct()
.forEach(System.out::println);
transactions.stream()
.map(Transaction::getValue)
.reduce(Integer::max);
transactions.stream()
.min(comparing(Transaction::getValue));
참고: Modern Java in Action (라울-게이브리얼 등 지음)