一、概述

  在java8中我们基本上都会使用到stream,尤其是里面的并行流。使用流的时候就不可避免的会使用到collect(进行数据的收集,因为现在的数据都是流,需要收集转化为对象进行使用),stream里面有2个collect的方法,如下:

collect(Collector<? super T,A,R> collector) 
collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)

  怎么说呢?虽然它给了2个方法使用,但是实际上这两个方法是差不多的,只不过一个需要你传输一个collector对象,一个需要你传输3个对象;但是一个collector对象里面已经包含了那3个参数,需要你在实现类的时候将这些方法都写上。

  但是,既然人家给了两个方法肯定是有所不同的,不同的地方在于collector对象,人家已经给了几种方式,具体的可以看看 Collectors(有转数组。list等的方法)。所以这里我就不再对collector这个对象过多的说明,其实我说明另外一个方法的时候,这个方法你也就明白的差不多了。

  以下我就主要说明一下这个方法:

collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)

二、参数说明

1、Supplier supplier

  这个的意思就是提供者的意思,就是向外提供一个对象,这是一个函数式接口,只需要实现其中的一个方法就可以(采用lambda或者直接实现类都是可以的)。而且这个类对象再这个collect方法中的作用就是创建一个对象,一个最终输出结果的对象。

2、BiConsumer<R,? super T> accumulator

  这个一个接受两个参数的消费者,什么是消费?就是吃进去不会吐出来,所以这个函数时接口的实现方法没有返回,只有里面自己的消费,这个接口要实现的方法是accpet,这个接口方法会被传入2个参数,这两个参数如下:

  • 第一个参数是提供者提供的对象,也就是最终作为结果要返回的对象。
  • 第二个参数是流里面的数据,要进行循环的数据

  有了这两个参数我们就可以再消费者的内部进行数据的操作与设置。

3、BiConsumer<R,R> combiner)

  这个类和上面第二类对象是一摸一样的,但是在这里实现的功能是不一样的,它传入的参数也是两个,但是这两个参数和上面的稍微有些区别,因为这两参数都是提供者提供的对象,那么这两个参数哪里不一样了?有什么作用呢?

  1. 哪里不一样?

  首先我们要明白一个地方,就是这个参数用在哪里?collect的第三个参数,也就是我们要说明的这个对象,它主要是用在并行流中,在非并行流中是没有任何作用的,也不会被执行到,所以它只能使用在并行流,只能在并行流中起作用。

  所以这两个参数哪里不一样就容易明白了,当我们使用并行流的时候,对象提供者就会提供多个一摸一样的对象,只不过是在并行线程中执行,他们各自执行各自的。所以两个对象就是并行流中其中2个提供者的对象。那么作用是什么呢?

  1. 有什么作用?

  其实到了这里作用已经是比较明显了,而且collect方法的第三个参数的参数名称也是能够很好的体现这个参数的所用的,就是合并。当我们在并行流中各自执行完成之后,如果你没有合并,你返回收集的只是其中一个提供这提供的对象,并不完整,所以这里我们进行各个对象的合并,这样我们返回收集的就是各个线程执行之后的结果了。

三、示例

List<String> strList = Stream.builder()
                .add("aaa")
                .add("bbb")
                .add("ccc")
                .build().parallel()
                .collect(() -> new ArrayList<String>(),
                        (list, str) -> list.add(String.valueOf(str)),
                        (list1, list2) -> list1.addAll(list2));