一、Stream 简介
在Java项目开发中,我们经常会用到数组和集合,然后经常需要对数组或者集合中元素进行处理,例如:筛选、排序、聚合等等。在Java8之前,处理数组或者集合中的元素往往都是千篇一律地进行遍历,不是很便捷。而在Java8中,引入了stream新特性,它专注于对数组或者集合进行一系列的操作,就像流水线一样,使得代码高效、简洁。
Java8 提供的Stream API将集合中的元素抽象为流,流在管道中进行传输,管道上的节点可以对流的进行一系列的处理(筛选、排序、聚合等等)。
二、Stream的操作流程
1) 第一步:将集合转换成stream流
2) 第二步:对stream流进行操作,包括中间操作(intermediate operation)和终端操作(terminal operation)
stream在管道中会经过各种中间操作(intermediate operation)的处理,最后由终端操作(terminal operation)将流转换成想要的结果
数据源(数组或集合) -> 流 -> 中间操作 -> 终端操作
三、常用的Stream API
1)中间操作API
2)终端操作API
下面定义一个User类来演示stream操作相关的API,User类包含姓名、年龄、性别和籍贯四个成员变量。
public class User implement Comparable{
private String name;
private Integer age;
private Integer sex;
private String address;
// seter/geter方法...
// 实现Comparable接口
@Override
public int compareTo(User user) {
return age.compareTo(user.getAge());
}
}
// 构建集合list
List list= Arrays.asList(
new User("Captain-America", 34, 0, "New York"),
new User("Black-Widow", 28, 1, "Los Angeles"),
new User("Iron-Man", 30, 0, "New York"),
);
3.1 中间操作(Intermediate operation)
3.1.1 filter
filter()方法用来根据条件过滤集合中的元素
// 过滤年龄超过30岁的User用户对象
List users = list.stream().filter(user->user.getAge() >= 30).collect(Collectors.toList());
3.1.2 distinct
distinct()方法用来对集合中的元素去重,需要依赖集合中元素的hashCode()方法和equals()方法
// 对重复的User对象进行去重
List users = list.stream().distinct().collect(Collectors.toList());
3.1.3 limit
limit()方法接受一个整数n作为参数,用来返回集合中前n个元素
// 取前3个元素
List users = list.stream().limit(3).collect(Collectors.toList());
3.1.4 skip
skip()方法接受一个整数n作为参数,表示跳过集合的前n个元素,与limit()方法作用相反
// 跳过前2个元素
List users = list.stream().skip(2).collect(Collectors.toList());
3.1.5 map
map()是非常非常常用的一个方法,它接收一个函数作为参数,这个函数会被应该在每一个元素上,将元素转换成另一种新的类型的元素
// 获取所有User对象的地址
List addressList = list.stream().map(user-> user.getAddress()).distinct().collect(Collectors.toList());
3.1.6 flatMap
flatMap() 方法是并行流操作,将流中的每个值都转换成另一个流,然后把所有流连接成一个流
3.1.7 sorted
sorted() 用来对元素进行排序,需要流中的元素实现了Comparable接口,然后重写compareTo方法;或者是实现Comparator接口,然后重写compare方法
// 按年龄排序
List users = list.stream().sotred().collect(Collectors.toList());
2. 终端操作(Terminal Operation)
3.2.1 anyMatch
anyMatch() 用判断流中是否存在至少一个元素满足条件,返回结果boolean类型
// 判断是否满足至少一个User年龄大于30
boolean result = list.stream().anyMatch(user->user.getAge() > 30);
3.2.2 allMatch
allMatch() 用来判断流中所有元素是否都满足条件,返回结果为boolean类型
boolean result = list.stream().allMatch(user->user.getAge() > 30);
3.2.3 forEach
forEach()方法是对流中的元素进行遍历,返回结果为void
// 打印address
list.stream().map(user-> user.getAddress()).distinct().forEach(System.out::pringln);
3.2.4 count
count()方法用来统计流中的元素个数,返回结果为long
long result = list.stream().map(user-> user.getAddress()).distinct().count();
3.2.5 collect
collect()方法也是非常非常常用的终端操作API,可以流中元素进行收集到List、Set、Map中
List addressList = list.stream().map(user-> user.getAddress()).collect(Collector.toList());
Set addressSet = list.stream().map(user-> user.getAddress()).distince().collect(Collector.toSet());
/**
* Function.identity() 方法表示流中的元素本身,即User类型的对象
* (v1, v2) -> v2) 表示如果出现重复的key,则只保留一个
**/
Map userMap = list.stream().collect(Collector.toMap(User::getName(), Function.identity(), (v1, v2) -> v2));