在Stream中有一個名為collect終止操作,其函數(shù)聲明如下
<R, A> R collect(Collector<? super T, A, R> collector);
這個操作的作用是將Stream中的T類型元素通過Collector 中的A類型的可變?nèi)萜?,最終reduce為R類型數(shù)據(jù)
而Collectors是Collecor的工具類,在Collectors里面實現(xiàn)了諸多有用的Collecor
通過上述的說明,你可能還是不太明白,那么舉一個小的例子:
String []strArray={"hello","world"};
List<String> strList=Arrays.stream(strArray).collect(Collectors.toList());
這個例子將String類型的Stream 通過collect函數(shù)收集為一個List類型
Collector
Collector是一個接口,其聲明如下:
Interface Collector<T,A,R>
其中的泛型含義如下:
- T - Stream中包含的元素類型
- A - 中間容器類型
- R - 結果數(shù)據(jù)類型
A Collector 由四個函數(shù)配合工作:
- 創(chuàng)建一個新的容器 (
supplier()) - 將元素添加到容器中(
accumulator()) - 將兩個容器合并為一個 (
combiner()) - 對容器執(zhí)行一個最終的轉換 (
finisher())
這些函數(shù)的工作流程如下
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的實現(xiàn),他包含了很多有用的reduce操作,比如將元素收集到集合之中,統(tǒng)計元素個數(shù),分組等操作
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);
//分組,先根據(jù)部門分組然后根據(jù)年齡分組
Map<String, Map<Integer, List<Employee>>> groupMap = employees.stream().collect(Collectors.groupingBy(Employee::getDept, Collectors.groupingBy(Employee::getAge)));
System.out.println("先根據(jù)部門分組然后根據(jù)年齡分組:" + groupMap);
//各個部門的人數(shù)
Map<String, Long> countMap = employees.stream().collect(Collectors.groupingBy(Employee::getDept, Collectors.counting()));
System.out.println("各個部門的人數(shù):" + countMap);
}
}
運行結果:
工資最高的員工是: Employee{name='e7', age=24, salary=17000, dept='IT'}
員工的平均工資為: 11571.42857142857
員工名單: <e1,e2,e3,e4,e5,e6,e7>
先根據(jù)部門分組然后根據(jù)年齡分組:{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'}]}}
各個部門的人數(shù):{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