Stream的collect方法传入的是Collector接口
一般博客介绍都是传入的Collectors.toList()这个方法,源码:
问题:
1.我想知道这个toList方法是怎么获取源stream对象的,对象是怎么被转成list的,这个调用过程是怎样的
2.toList()方法的第二个参数是怎么确定List类型的 ,其形参是BiConsumer accumulator,实参是List::add, 实参List类型是如何确定的
1大致代码类似
List toList(stream) {
List result = new List();
while (stream.hasNext())
list.add(next());
return list;
}
2Java编译器有类型推定,collection前面的stream返回值类型可以推定出来,并且得知toList的类型
1.stream对象是上一个方法返回的返回值。
比如
Stream.of("a", "b", "c").map(String::toUpperCase).collect(Collectors.toList());
调用map的对象是Stream.of返回的,调用collect的对象是map返回的。
2.是由Stream对象确定的。
先看collect方法:
@Override
@SuppressWarnings("unchecked")
public final <R, A> R collect(Collector<? super P_OUT, A, R> collector) {
A container;
if (isParallel()
&& (collector.characteristics().contains(Collector.Characteristics.CONCURRENT))
&& (!isOrdered() || collector.characteristics().contains(Collector.Characteristics.UNORDERED))) {
container = collector.supplier().get();
BiConsumer<A, ? super P_OUT> accumulator = collector.accumulator();
forEach(u -> accumulator.accept(container, u));
}
else {
container = evaluate(ReduceOps.makeRef(collector));
}
return collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)
? (R) container
: collector.finisher().apply(container);
}
P-OUT可以由stream对象提供,看Stream就知道了。再看toList函数:
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
P-OUT就传递给了T所以他的类型就确定了。