Java8 应该算是业界主版本了,版本中重要性很高的一个更新是Stream流处理。关于流处理内容比较多,本文主要是说一下Stream中的Collectors工具类的使用。
Collectors是java.util.stream包下的一个工具类,其中各个方法的返回值可以作为java.util.stream.Stream#collect的入参,实现对队列的各种操作,包括:分组、聚合等。官方文档给出一些例子:
Implementations of {@link Collector} that implement various useful reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc.
The following are examples of using the predefined collectors to perform common mutable reduction tasks:
// Accumulate names into a List
List
// Accumulate names into a TreeSet
Set
// Convert elements to strings and concatenate them, separated by commas
String joined = things.stream()
.map(Object::toString)
.collect(Collectors.joining(", "));
// Compute sum of salaries of employee
int total = employees.stream()
.collect(Collectors.summingInt(Employee::getSalary)));
// Group employees by department
Map
.collect(Collectors.groupingBy(Employee::getDepartment));
// Compute sum of salaries by department
Map
.collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));
// Partition students into passing and failing
Map
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
先定义待操作对象,一个万能的Student类(用到了 lombok):
- @Data
- @AllArgsConstructor
- public class Student {
- private String id;
- private String name;
- private LocalDate birthday;
- private int age;
- private double score;
- }
然后定义一组测试数据:
- final List<Student> students = Lists.newArrayList();
- students.add(new Student("1", "张三", LocalDate.of(2009, Month.JANUARY, 1), 12, 12.123));
- students.add(new Student("2", "李四", LocalDate.of(2010, Month.FEBRUARY, 2), 11, 22.123));
- students.add(new Student("3", "王五", LocalDate.of(2011, Month.MARCH, 3), 10, 32.123));
这个比较简单,就是统计聚合结果的元素数量:
- // 3
- students.stream().collect(Collectors.counting())
这几个方法是计算聚合元素的平均值,区别是输入参数需要是对应的类型。
比如,求学生的分数平均值,因为分数是double类型,所以在不转类型的情况下,需要使用averagingDouble:
- // 22.123
- students.stream().collect(Collectors.averagingDouble(Student::getScore))
如果考虑转换精度,也是可以实现:
- // 22.0
- students.stream().collect(Collectors.averagingInt(s -> (int)s.getScore()))
- // 22.0
- students.stream().collect(Collectors.averagingLong(s -> (long)s.getScore()))
如果是求学生的平均年龄,因为年龄是int类型,就可以随意使用任何一个函数了:
- // 11.0
- students.stream().collect(Collectors.averagingInt(Student::getAge))
- // 11.0
- students.stream().collect(Collec