Java8新特性 – Stream流
1. 什么是Stream流?
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作 。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性.
2. Stream流的基本使用
前提:学习Stream流需要了解Lambda表达式,如果有不会Lambda的可以看看我的另一篇博客
假设我们有一个简单学生类,只有姓名和年龄两个属性。
public class Student {
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
给定一个list集合
List<Student> list = Arrays.asList(
new Student("zhangsan",18),
new Student("lisi",16),
new Student("xuanwu",8),
new Student("xiaoming",19),
new Student("lili",15),
new Student("nana",25)
);
若我们要获取list集合中所有学生的姓名,存入一个集合中,我们该如何实现。
// 使用以前的方法
List<String> names = new ArrayList<>();
for (Student student : list) {
names.add(student.getName);
}
可以发现,我们必须依次遍历整个list集合,取出name属性。而如果我们使用Stream流,则不管是代码简洁度还是效率上都得到大大的提升。
list.stream().map(Student::getName).collect(Collectors.toList());// 一行即可解决
3. Stream流的具体使用方法
对比list.stream().map(Student::getName).collect(Collectors.toList());
我们来简单了解下。
Stream流在使用过程中有三个阶段:
- 生成并构造一个流 list.stream()
- 在流的处理过程中添加、绑定惰性求值流程 map(Student::getName)
- 对流使用强制求值函数,生成最终结果 collect(Collectors.toList())
对应的方法详解:
- map 方法用于映射每个元素到对应的结果。map(Student::getName) 映射每一个Student,得到对应的姓名
- Collectors 类实现了很多归约操作, 例如将流转换成集合和聚合元素 。 collect(Collectors.toList())将流转为list集合。
4. Stream流的其他API接口应用举例
4.1 filter 方法用于通过设置的条件过滤出元素。
// 获取年龄大于15的所有学生
List<Student> students = list.stream()
.filter(student -> student.getAge() > 15)
.collect(Collectors.toList());
// 获取年龄大于15的所有学生的姓名
List<String> names = list.stream()
.filter(student -> student.getAge()>15) .map(Student::getName)
.collect(Collectors.toList());
4.2 allMatch 方法用于通过条件判断集合是否合法。
// 匹配是否所有学生都大于18岁
boolean b = list.stream().allMatch(student -> student.getAge() > 18);
// 返回false 因为存在18岁以下的学生
4.3 sorted 方法用于对流进行排序。
// 获取年龄大于18的学生的名字并且按照年龄从小到大排序
List<String> names = list.stream()
.filter(student -> student.getAge() > 18)
.sorted(Comparator.comparingInt(Student::getAge))
.map(Student::getName)
.collect(Collectors.toList());
4.4 Collectors.toMap() 方法用于返回map集合
// 将年龄大于18的筛选出放入新的map key为年龄 value为姓名 并且key重复覆盖
Map<Integer, String> map = list.stream()
.filter(student -> student.getAge() > 18)
.collect(Collectors.toMap(Student::getAge, Student::getName,(x,y) -> y));
// (x,y) -> y 指 如果有重发的key 则后面的key覆盖前面的key
4.5 Collectors.groupingBy() 方法用于按条件分组
// 将年龄进行分组, key 为年龄 value 为 年龄对应的student集合
Map<Integer, List<Student>> collect = list.stream()
.collect(Collectors.groupingBy(Student::getAge));
4.6 Collectors.joining() 方法用于合并集合中的字符串
String collect = list.stream().map(Student::getName).collect(Collectors.joining());
// 打印 : zhangsanlisixuanwuxiaominglilinanakuku
5. 总结
本篇博客并不是带大家深入了解Stream流的具体实现步骤,底层源码。而是简单介绍Stream流的简单用法和API的调用。不过一些简单的API实现原理我相信大家还是可以理解的。例如 map 方法:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
看过我的Lambda表达式的那篇博客基本可以看出 Function接口的含义。不止这个,filter方法等等都有在Lmbda中提到过。