IDENTITY_FINISH的字段特别重要,在这里使用
第三步: makeRef(), 逐步调用者三个函数式接口对象 public static <T, I> TerminalOp<T, I> makeRef(Collector<? super T, I, ?> collector) { Supplier<I> supplier = Objects.requireNonNull(collector).supplier(); BiConsumer<I, ? super T> accumulator = collector.accumulator(); BinaryOperator<I> combiner = collector.combiner(); class ReducingSink extends Box<I> implements AccumulatingSink<T, I, ReducingSink> { @Override public void begin(long size) { state = supplier.get(); } @Override public void accept(T t) { accumulator.accept(state, t); } @Override public void combine(ReducingSink other) { state = combiner.apply(state, other.state); } } return new ReduceOp<T, I, ReducingSink>(StreamShape.REFERENCE) { @Override public ReducingSink makeSink() { return new ReducingSink(); } @Override public int getOpFlags() { return collector.characteristics().contains(Collector.Characteristics.UNORDERED) ? StreamOpFlag.NOT_ORDERED : 0; } }; } Collector的一些"坑"使用这个案例去理解运作过程.
把一个set集合进行收集,我们对结果做一个增强.(原来是直接放在set当中了.)我们现在放在Map当中.
声明一个Collector类,要求.
输入:Set
输出:Map<String,String>
示例输入:["hello","world","hello world"]
示例输出:[{hello,hello},{world,world},{hello world,hello world}
泛型:<T,T,T>
彻底理解Characteristics.IDENTITY_FINISH属性 package com.dawa.jdk8.stream2; import java.util.*; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; public class MySetCollector2<T> implements Collector<T, Set<T>, Map<T,T>> { @Override public Supplier<Set<T>> supplier() { System.out.println("supplier invoked"); return HashSet<T>::new; } @Override public BiConsumer<Set<T>, T> accumulator() { System.out.println("accumulator invoked"); return Set::add; } @Override public BinaryOperator<Set<T>> combiner() { System.out.println("combiner invoked"); return (set1, set2) -> { set1.addAll(set2); return set1; }; } @Override public Function<Set<T>, Map<T, T>> finisher() { //这里一定会被调用.因为结果类型和最终类型不同 //示例输入:["hello","world","hello world"] //示例输出:[{hello,hello},{world,world},{hello world,hello world} System.out.println("finisher invoked"); return set ->{ Map<T, T> map = new HashMap<>(); set.stream().forEach(item -> map.put(item, item)); return map; }; } @Override public Set<Characteristics> characteristics() { System.out.println("characteristics invoked"); return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED)); } public static void main(String[] args) { List<String> list = Arrays.asList("hello", "world", "hello", "welocome", "a", "b", "c", "d", "e"); HashSet<String> set = new HashSet<>(list); System.out.println("set:"+list); Map<String, String> collect = set.stream().collect(new MySetCollector2<>()); System.out.println(collect); } }如果多一个参数:
return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED,Characteristics.IDENTITY_FINISH));则会出现类型转换异常.
/** * Indicates that the finisher function is the identity function and * can be elided. If set, it must be the case that an unchecked cast * from A to R will succeed. */ IDENTITY_FINISH如果定义这个属性,则代表 indentity和 finish 是同一个类型的,要执行强制类型转换.所以会出现上述异常.
收集器是什么特性的,都是由这个Characteristics类来由你定义的.
所以你必须要理解你写的程序的类型.才能正确的使用这个枚举定义类.
彻底理解Characteristics.CONCURRENT属性分支合并框架ForkJoinPoll(并行流)
对程序进行一定的改造,打印出相应的线程名称
@Override public BiConsumer<Set<T>, T> accumulator() { System.out.println("accumulator invoked"); return (set,item)->{ System.out.println("accumulator:"+ Thread.currentThread().getName()); set.add(item); }; }串行情况下:
Map<String, String> collect = set.Stream().collect(new MySetCollector2<>());运行结果如下:
并行情况下
Map<String, String> collect = set.parallelStream().collect(new MySetCollector2<>());运行结果如下.