JAVA8学习——深入Comparator&Collector(学习过程) (3)

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<>());

运行结果如下:

image-20200105110718295

并行情况下

Map<String, String> collect = set.parallelStream().collect(new MySetCollector2<>());

运行结果如下.

image-20200105110746134

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpysfj.html