java8学习总结——Collector接口

来源:互联网 发布:unity 软件位置 编辑:程序博客网 时间:2024/06/16 06:08

概述

在JDK中对Collector的定义是一个可变的归约操作(A mutable reduction operation</a>)。是一种操作思想,分为计算元素、归集计算结果两个主要的步骤;为了保存计算元素的中间状态,所以会提供一个容器来完成中间状态和中间结果的保存。如下面的集合操作:

public class CollecorTest {    public static void main(String[] args) {            /**             * 对所有元素追击后缀“suffix”             * 再以map的形式输出,key和value都是元素本身             */            List<String> list = Arrays.asList("hello","world","welcome","yes","no");            List<String> container = new ArrayList<>();  //创建一个中间容器,用来保存中间状态            for (String element : list) {                container.add(element+"suffix");  //对中间元素进行操作,并存入容器中            }            Map<String,String> map = new HashMap<String,String>();            for (String element : container) {                map.put(element,element); //再次操作改变集合的形式,归集结果                      }    }}

在Collector接口提供四个方法:

             /**         *  1、Supplier<A> supplier();--> 不接受参数,返回一个值。充当提供容器的角色         *  2、BiConsumer<A, T> accumulator();--> 接收两个参数,不返回结果。其接收的两个参数,第一个是supplier提供的集合;第二个参数是待操作的元素,将元素操作完之后,放入集合中。         *  3、BinaryOperator<A> combiner(); --> 这个方法主要是应对并发操作时,会出现多个中间容器,需要通过conbiner方法将多个中间结果容器进行合并,因为在finnish中只会接收一个参数。如果不需要合并,则不会执行conbiner方法         *  4、Function<A, R> finishaer(); --> 接收一个参数,返回一个值。这是最后的归集操作,方法接收的参数就是accumulator或者是combiner产生的结果,也就是一个中间的结果集。中间结果集合通过finisher方法输出最终结果         */

所以Collector只是规定一种元素运算方式,或者说是一种运算规范,具体的运算内容可以自定义。


Collector的创建

源代码:

public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier,                                                 BiConsumer<A, T> accumulator,                                                 BinaryOperator<A> combiner,                                                 Function<A, R> finisher,                                                 Characteristics... characteristics) {        Objects.requireNonNull(supplier);        Objects.requireNonNull(accumulator);        Objects.requireNonNull(combiner);        Objects.requireNonNull(finisher);        Objects.requireNonNull(characteristics);        Set<Characteristics> cs = Collectors.CH_NOID;        if (characteristics.length > 0) {            cs = EnumSet.noneOf(Characteristics.class);            Collections.addAll(cs, characteristics);            cs = Collections.unmodifiableSet(cs);        }        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs);}

of方法返回的是一个CollectorImpl类。CollectorImpl是Collector中的一个静态内部类。这样做的原因主要是使用者不需要自己去定义实现类,然后再进行创建,减少使用者的工作量,同时又能够使代码更简洁优雅。

Collector的构造函数接收5个参数,前面四个(supplier,accumulator,combiner,finisher),这四个参数分别对应上面介绍的四个方法。最后一个参数使用来控制Collector的执行方式的。

1、  CONCURRENT  //将会以并行的方式进行操作

2、  UNORDERED   //不保证输出结果的顺序(没理解)

3、  IDENTITY_FINISH  //恒等函数,当传入这个值时,finisher函数将不会执行,而直接返回结果


IDENTITY_FINISH: 传入这个参数,finisher函数将会被认为是一个恒等函数。即:输出类型与输入类型完全一致。此时将不会再执行finisher方法,而是将中间结果集合进行强制类型转换得到最后的结果。源代码如下:

collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)               ? (R) container               :collector.finisher().apply(container)

CONCURRENT:

1、  传入这个参数,同时调用parallel()方法,supplier方法只会执行一次,并且会创建多个线程操作这个集合。

2、  不传入这个参数,同时调用parallel()方法,将会执行supplier()方法多次,创建多个线程操作多个容器。

3、  传入这个参数,不调用parallel()方法,supplier方法只会执行一次,不会创建多个线程,使用主线程执行操作。

原创粉丝点击