Java8 부터 지원한 stream을 사용하면서 filter, map, flatMap, collect가 어떤 기능을 위해 쓰는지는 필요에 의해 검색해가며 알긴 했지만, stream에 대해 궁금증이 생겼을 때 일단 동작하니 넘겼던 지난날의 근본없음을 반성하는 마음으로 공부해보게 되었다.
Modern JAVA In Action의 Chapter 4 ~ 6을 보며 새롭게 알게된 내용을 정리했다.
별도 sorted를 사용하지 않고, source가 순서가 있는 collection이라면 stream도 순서대로 소비된다.
즉, 순서가 유지된다.
source : 처음에 제공된 collection, array, I/O resource
collect가 호출되기 전까지 앞의 method들이 호출되고 chain이 queue에 쌓여있을거라 생각하지만,
collect(Terminal operation)가 호출되기 전까지는 결과 뿐만아니라 source의 요소도 선택되지 않는다.
중간 연산자(Intermediate operation)가 아예 수행되지 않고 기다린다.
-> lazy evaluation
전체 stream을 처리하지 않고, source 하나 씩 중간 연산들을 모두 수행하고, 요소가 발견되자 마자 결과가 생성된다. (limit도 동일)
-> short circuiting evaluation
List<String> names =
menu.stream()
.filter(dish -> {
System.out.println("filtering:" + dish.getName());
return dish.getCalories() > 300;
})
.map(dish -> {
System.out.println("mapping:" + dish.getName());
return dish.getName();
})
.limit(3)
.collect(toList());
System.out.println(names);
filtering:pork
mapping:pork
filtering:beef
mapping:beef
filtering:chicken
mapping:chicken
[pork, beef, chicken]
stream이 source collection 순서대로 처리하는데 stream API는 왜 findFirst와 findAny 비슷한 동작을 만들었을까?
parallel stream을 사용할 때, 어떤 요소가 반환되는지 신경쓰지 않으면 findAny를 사용한다.
Map<Currency, List<Transaction>> transactionsByCurrencies =
transactions.stream()
.collect(groupingBy(Transaction::getCurrency));
public interface Collector<T, A, R>
Classification of an item in the stream during the grouping process
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
Function<A, R> finisher();
BinaryOperator<A> combiner();
Set<Characteristics> characteristics();
}