查找
allMatch,是否全部都满足指定的参数行为,返回值为布尔值,如:
boolean allOver18 = students.stream().allMatch(student -> student.getAge() >= 18);
noneMatch,是否不存在满足指定行为的元素,返回值为布尔值,如:
//是否没一个学生是18岁以上的 boolean noneIsOver18 = students.stream().noneMatch(student -> student.getAge() >= 18);
findFirst,必须配合filter()使用,返回满足条件的第一个元素,返回值是Stream对应的Optiona,如:
Optional<Student> optStu = students.stream().filter(student -> student.getAge() >= 18).findFirst();
findAny,findAny相对于findFirst的区别在于,findAny不一定返回第一个,而是返回任意一个,因此,对于顺序流式处理,findFirst和findAny返回的结果是一样的,当并行流式处理的时候,查找第一个元素往往会有很多限制,如果不是特别需求,在并行流式处理中使用findAny的性能要比findFirst好。
归约
前面的例子中我们大部分都是通过collect(Collectors.toList())对数据封装返回,如我的目标不是返回一个新的集合,而是希望对经过参数化操作后的集合进行进一步的运算,那么我们可用对集合实施归约操作。java8的流式处理提供了reduce方法来达到这一目的。前面我们通过mapToInt将Stream<Student>映射成为IntStream,并通过IntStream的sum方法求得所有学生的年龄之和,实际上我们通过归约操作,也可以达到这一目的,实现如下:
// 前面例子中的方法 int totalAge = students.stream() .filter(student -> "计算机科学".equals(student.getMajor())) .mapToInt(Student::getAge).sum(); // 归约操作 int totalAge = students.stream() .filter(student -> "计算机科学".equals(student.getMajor())) .map(Student::getAge) .reduce(0, (a, b) -> a + b); // 进一步简化 int totalAge2 = students.stream() .filter(student -> "计算机科学".equals(student.getMajor())) .map(Student::getAge) .reduce(0, Integer::sum); // 采用无初始值的重载版本,需要注意返回Optional Optional<Integer> totalAge = students.stream() .filter(student -> "计算机科学".equals(student.getMajor())) .map(Student::getAge) .reduce(Integer::sum); // 去掉初始值
分组
在数据库操作中,我们可以通过GROUP BY关键字对查询到的数据进行分组,java8的流式处理也为我们提供了这样的功能Collectors.groupingBy来操作集合。比如我们可以按学校对上面的学生进行分组:
上面演示的是一级分组,我们还可以定义多个分类器实现 多级分组,比如我们希望在按学校分组的基础之上再按照专业进行分组,实现如下:
Map<String, Map<String, List<Student>>> groups2 = students.stream().collect( Collectors.groupingBy(Student::getSchool, // 一级分组,按学校 Collectors.groupingBy(Student::getMajor))); // 二级分组,按专业
总结:Java8的函数很好用,可以让程序简单简洁,所以要熟知每个函数的写法以及应用场景。