Java 8 Stream collect()

1. 简介

在本文中,我们将讨论Java 8 Stream.collect()。此方法对流元素执行可变的约简操作。

通过更新而不是替换将流元素合并到结果中。

Stream.collect()使用lambda表达式将一个参数用作收集器,将三个参数用作供应器(Supplier),累加器(Accumulator)和组合器(Combiner)。

2. 使用供应商,累加器和合并器的Stream.collect()

Stream.collect()使用供应商,累加器,合并器的定义如下:

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

supplier:创建一个新的结果容器,该容器将由累加器和组合器填充,最后将由collect()方法返回。在并行处理中,Supplier将多次调用该函数,每次将返回新值。 accumulator:将其他元素合并到结果中。 combiner:组合两个必须与累加器兼容的值。合并器在并行处理中工作。

我们来看一个示例:

    @Test
    public void test_StreamCollect(){
        List<String> list = Arrays.asList("A", "B", "C");
        String parallelResult = list.parallelStream().collect(StringBuilder::new,
                (response, element) -> response.append(" ").append(element),
                (response1, response2) -> response1.append(",").append(response2.toString()))
                .toString();
        String result = list.stream().collect(StringBuilder::new,
                (response, element) -> response.append(" ").append(element),
                (response1, response2) -> response1.append(",").append(response2.toString()))
                .toString();
        System.out.println("Result: " + result);
        System.out.println("Parallel Result: " + parallelResult);
    }

输出结果如下:

Result:  A B C
Parallel Result:  A, B, C

并行和非并行的结果不太一样,list.stream()不是并行处理,因此不会使用到合并器,最终的输出也就没有了逗号。

3. 使用Collector的Stream.collect()

Stream.collect()也接受单个参数。

定义如下:

<R,A> R collect(Collector<? super T,A,R> collector)

可以通过Collector执行许多操作,例如求和,分组,联接等。

这里给大家举几个例子。

3.1 Collectors.summarizingInt()

    @Test
    public  void  test_StreamCollect_summarizingInt(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        IntSummaryStatistics stats = list.stream()
                .collect(Collectors.summarizingInt(i -> i));
        System.out.println("Sum:"+stats.getSum());
    }

输出结果:

Sum:21

3.2 Collectors.joining()

    @Test
    public  void  test_StreamCollect_joining(){
        List<String> list = Arrays.asList("A","B","C","D");
        String result=  list.stream().collect(Collectors.joining(", "));
        System.out.println("Joining Result: "+ result);
    }

输出结果:

Joining Result: A, B, C, D

3.3 Collectors.averagingInt()

    @Test
    public  void  test_StreamCollect_averagingInt(){
        List<Integer> list = Arrays.asList(1,2,3,4);
        Double result = list.stream().collect(Collectors.averagingInt(v-> v ));
        System.out.println("Average: "+result);
    }

输出结果:

Average: 2.5

3.4 Collectors.counting()

    @Test
    public  void  test_StreamCollect_counting(){
        List<Integer> list = Arrays.asList(1,2,3,4);
        long result=  list.stream().collect(Collectors.counting());
        System.out.println("Count: "+ result);
    }

输出结果:

Count: 4

3.5 Collectors.toList()

    @Test
    public  void  test_StreamCollect_toList(){
        String[] strArray = {"AA", "BB", "CC"};
        List<String> list = Arrays.stream(strArray).collect(Collectors.toList());
        list.forEach(s->System.out.println(s));
    }

输出结果:

AA
BB
CC

3.6 Collectors.toMap

		@Test
    public  void  test_StreamCollect_toMap(){
        List<Person> list = new ArrayList<>();
        list.add(new Person(100, "A"));
        list.add(new Person(200, "B"));
        list.add(new Person(300, "C"));
        Map<Integer, String> map = list.stream()
                .collect(Collectors.toMap(Person::getId, Person::getName));
        map.forEach((x, y) -> System.out.println("Key: " + x +", value: "+ y));
    }

    class Person {
        private Integer id;
        private String name;
        public Person(Integer id, String name) {
            this.id = id;
            this.name = name;
        }
        public Integer getId() {
            return id;
        }
        public String getName() {
            return name;
        }
    }

输出结果:

Key: 100, value: A
Key: 200, value: B
Key: 300, value: C

4. 总结

在本文中,我们讨论了Java 8 Stream.collect()的两个重载方法

  • 使用供应商,累加器和合并器的
  • 使用Collector,并通过API提供的工具类Collectors,列举了几个常用的Collector。

与往常一样,可以在GitHub上获得代码示例。