Stream
1. 流式处理简介
比如我们希望对一个包含整数的集合中筛选出所有的偶数,并将其封装成为一个新的List返回,那么在java8之前,我们需要通过如下代码实现:
List<Integer> evens = new ArrayList<>();
for (final Integer num : nums) {
if (num % 2 == 0) {
evens.add(num);
}
}
通过java8的流式处理,我们可以将代码简化为:
List<Integer> evens = nums.stream().filter(num -> num % 2 == 0).collect(Collectors.toList());
这里列表遍历,之所以可以简化为lamda表达式,是因为jdk8以后为lambda表达式已经内置了丰富的函数式接口,这里使用的就是jdk自带的Predicate函数式接口。
将以上lambda表达式还原成匿名内部类,如下:
List<Integer> evens = nums.stream().filter(new Predicate<Integer>() {
@Override
public boolean test(Integer num) {
return num % 2 == 0;
}
}).collect(Collectors.toList());
先简单解释一下上面这行语句的含义,stream()操作将集合转换成一个流,filter()执行我们自定义的筛选处理,这里是通过lambda表达式筛选出所有偶数,最后我们通过collect()对结果进行封装处理,并通过Collectors.toList()指定其封装成为一个List集合返回。
一个流式处理可以分为三个部分:转换成流、中间操作、终端操作。
-
一个流式处理的操作我们首先需要调用stream()函数将其转换成流,
-
然后再调用相应的中间操作达到我们需要对集合进行的操作,比如筛选、转换等,
-
最后通过终端操作对前面的结果进行封装,返回我们需要的形式。
2. 中间操作
2.1过滤
2.1.1 filter
其定义为:Stream filter(Predicate<? super T> predicate),
-
filter接受一个谓词Predicate,我们可以通过这个谓词定义筛选条件,
-
在介绍lambda表达式时我们介绍过Predicate是一个函数式接口,其包含一个test(T t)方法,该方法返回boolean。
现在我们希望从集合students中筛选出所有武汉大学的学生,那么我们可以通过filter来实现,并将筛选操作作为参数传递给filter:
List<Student> whuStudents = students.stream()
.filter(student -> "武汉大学".equals(student.getSchool()))
.collect(Collectors.toList());
2.1.2 distinct
distinct操作类似于我们在写SQL语句时,添加的DISTINCT关键字,用于去重处理,distinct基于Object.equals(Object)实现,回到最开始的例子,假设我们希望筛选出所有不重复的偶数,那么可以添加distinct操作:
List