1. 函数第一种调用方式的接口如下
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
- supplier 这个参数就是提供一个容器 , 可以看到最后 collect 操作的结果是一个 R 类型变量 , 而 supplier 接口最后需要返回的也是一个 R 类型的变量 , 所以说这里返回的是收集元素的容器 。
- accumulator 参数 , 看到这个函数的定义是传入一个 R 容器 , 后面则是 T 类型的元素 , 需要将这个 T 放到 R 容器中 , 即这一步是用来将元素添加到容器中的操作 。
- conbiner 这个参数是两个容器 , 即当出现多个容器的时候容器如何进行聚合 。
String concat = stringStream.collect(StringBuilder::new, StringBuilder::Append,StringBuilder::append).toString();//等价于上面,这样看起来应该更加清晰String concat = stringStream.collect(() -> new StringBuilder(),(l, x) -> l.append(x), (r1, r2) -> r1.append(r2)).toString();
2. Collector 接口第二种方案是更高级的用法采用了 Collector 接口: <R, A> R collect(Collector<? super T, A, R> collector);
可以看到他返回的还是一个 R 类型的变量 , 也就是容器 。Collector接口是使得collect操作强大的终极武器,对于绝大部分操作可以分解为旗下主要步骤,提供初始容器->加入元素到容器->并发下多容器聚合->对聚合后结果进行操作
static class CollectorImpl<T, A, R> implements Collector<T, A, R> { private final Supplier<A> supplier; private final BiConsumer<A, T> accumulator; private final BinaryOperator<A> combiner; private final Function<A, R> finisher; private final Set<Characteristics> characteristics; CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner, Function<A,R> finisher, Set<Characteristics> characteristics) { this.supplier = supplier; this.accumulator = accumulator; this.combiner = combiner; this.finisher = finisher; this.characteristics = characteristics;} CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner, Set<Characteristics> characteristics) { this(supplier, accumulator, combiner, castingIdentity(), characteristics);}@Override public BiConsumer<A, T> accumulator() { return accumulator;}@Override public Supplier<A> supplier() { return supplier;}@Override public BinaryOperator<A> combiner() { return combiner;}@Override public Function<A, R> finisher() { return finisher;}@Override public Set<Characteristics> characteristics() { return characteristics;}}
可以看到我们可以直接 new CollectorImpl 然后将这些函数传入 , 另外还有一种简单的方式就是 使用 Collector.of()依然可以直接传入函数 。和 new CollectorImpl 是等价的 。3. 工具函数1. toList()容器: ArrayList::new
加入容器操作: List::add
多容器合并: left.addAll(right); return left;
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);}
2.joining()容器: StringBuilder::new加入容器操作: StringBuilder::append
多容器合并: r1.append(r2); return r1;
聚合后的结果操作: StringBuilder::toString
public static Collector<CharSequence, ?, String> joining() { return new CollectorImpl<CharSequence, StringBuilder, String>(StringBuilder::new, StringBuilder::append,(r1, r2) -> { r1.append(r2); return r1; },StringBuilder::toString, CH_NOID);}
3.groupingBy()roupingBy是toMap的一种高级方式,弥补了toMap对值无法提供多元化的收集操作,比如对于返回Map<T,List<E>>这样的形式toMap就不是那么顺手,那么groupingBy的重点就是对Key和Value值的处理封装.分析如下代码,其中classifier是对key值的处理,mapFactory则是指定Map的容器具体类型,downstream为对Value的收集操作. public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) {.......}
一个简单的例子//原生形式Lists.<Person>newArrayList().stream().collect(() -> new HashMap<Integer,List<Person>>(),(h, x) -> { List<Person> value = https://www.isolves.com/it/cxkf/yy/JAVA/2021-07-04/h.getOrDefault(x.getType(), Lists.newArrayList()); value.add(x); h.put(x.getType(), value);},HashMap::putAll);//groupBy形式Lists.
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- javascript10个实用小技巧
- 移动电源|新一代差旅神器!魅族PANDAER 130W可视移动电源开售:999元
- 线上debug诊断神器-Arthas
- Linux下查找java进程耗用cpu最高的线程方法
- JavaScript 中的“提升”是怎么回事?
- Java不停机监控&热操作
- 使用java开发微信公众号系列-公共类
- 浅谈java中重写和重载的区别
- 网络扫描神器Nmap常用操作方法详解以及使用脚本爆破telnet密码
- 详解Java反序列化漏洞