美文网首页java lambda
Collector和Collectors

Collector和Collectors

作者: spraysss | 来源:发表于2019-08-04 15:15 被阅读0次

    在Stream中有一个名为collect终止操作,其函数声明如下

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

    这个操作的作用是将Stream中的T类型元素通过Collector 中的A类型的可变容器,最终reduce为R类型数据
    而Collectors是Collecor的工具类,在Collectors里面实现了诸多有用的Collecor
    通过上述的说明,你可能还是不太明白,那么举一个小的例子:

     String []strArray={"hello","world"};
     List<String> strList=Arrays.stream(strArray).collect(Collectors.toList());
    

    这个例子将String类型的Stream 通过collect函数收集为一个List类型

    Collector

    Collector是一个接口,其声明如下:

    Interface Collector<T,A,R>
    

    其中的泛型含义如下:

    • T - Stream中包含的元素类型
    • A - 中间容器类型
    • R - 结果数据类型

    A Collector 由四个函数配合工作:

    这些函数的工作流程如下

         A a1 = supplier.get();
         accumulator.accept(a1, t1);
         accumulator.accept(a1, t2);
         R r1 = finisher.apply(a1);  // result without splitting
    
         A a2 = supplier.get();
         accumulator.accept(a2, t1);
         A a3 = supplier.get();
         accumulator.accept(a3, t2);
         R r2 = finisher.apply(combiner.apply(a2, a3));  // result with splitting
    

    Collectors

    Collectors是对Collector的实现,他包含了很多有用的reduce操作,比如将元素收集到集合之中,统计元素个数,分组等操作

    Collectors使用实例

    package com.example.lambda;
    
    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    public class CollectorsTest {
        static class Employee {
            private String name;
            private int age;
            private int salary;
            private String dept;
    
            Employee(String name, int age, int salary, String dept) {
                this.name = name;
                this.age = age;
                this.salary = salary;
                this.dept = dept;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public int getAge() {
                return age;
            }
    
            public void setAge(int age) {
                this.age = age;
            }
    
            public int getSalary() {
                return salary;
            }
    
            public void setSalary(int salary) {
                this.salary = salary;
            }
    
            public String getDept() {
                return dept;
            }
    
            public void setDept(String dept) {
                this.dept = dept;
            }
    
            @Override
            public String toString() {
                return "Employee{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        ", salary=" + salary +
                        ", dept='" + dept + '\'' +
                        '}';
            }
        }
    
        public static void main(String[] args) {
            Employee e1 = new Employee("e1", 20, 8000, "BS");
            Employee e2 = new Employee("e2", 21, 7500, "BS");
            Employee e3 = new Employee("e3", 22, 7500, "CW");
            Employee e4 = new Employee("e4", 23, 10000, "CW");
            Employee e5 = new Employee("e5", 24, 15000, "IT");
            Employee e6 = new Employee("e6", 25, 16000, "IT");
            Employee e7 = new Employee("e7", 24, 17000, "IT");
            List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5, e6, e7);
            //找出工资最高的员工
            employees.stream().collect(Collectors.maxBy(Comparator.comparingInt(Employee::getSalary))).ifPresent(e -> {
                System.out.println("工资最高的员工是: " + e);
            });
            //员工的平均工资
            Double avgSalary = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
            System.out.println("员工的平均工资为: " + avgSalary);
            //员工名单
            String empNames = employees.stream().map(Employee::getName).collect(Collectors.joining(",", "<", ">"));
            System.out.println("员工名单: " + empNames);
    
            //分组,先根据部门分组然后根据年龄分组
            Map<String, Map<Integer, List<Employee>>> groupMap = employees.stream().collect(Collectors.groupingBy(Employee::getDept, Collectors.groupingBy(Employee::getAge)));
            System.out.println("先根据部门分组然后根据年龄分组:" + groupMap);
            //各个部门的人数
            Map<String, Long> countMap = employees.stream().collect(Collectors.groupingBy(Employee::getDept, Collectors.counting()));
            System.out.println("各个部门的人数:" + countMap);
        }
    }
    
    

    运行结果:

    工资最高的员工是: Employee{name='e7', age=24, salary=17000, dept='IT'}
    员工的平均工资为: 11571.42857142857
    员工名单: <e1,e2,e3,e4,e5,e6,e7>
    先根据部门分组然后根据年龄分组:{BS={20=[Employee{name='e1', age=20, salary=8000, dept='BS'}], 21=[Employee{name='e2', age=21, salary=7500, dept='BS'}]}, CW={22=[Employee{name='e3', age=22, salary=7500, dept='CW'}], 23=[Employee{name='e4', age=23, salary=10000, dept='CW'}]}, IT={24=[Employee{name='e5', age=24, salary=15000, dept='IT'}, Employee{name='e7', age=24, salary=17000, dept='IT'}], 25=[Employee{name='e6', age=25, salary=16000, dept='IT'}]}}
    各个部门的人数:{BS=2, CW=2, IT=3}
    

    参考

    https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
    https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html

    相关文章

      网友评论

        本文标题:Collector和Collectors

        本文链接:https://www.haomeiwen.com/subject/rqrprctx.html