jdk1.8的两个重大改变,一个是Lambda表达式,另一个就是Stream API。Stream是jdk8中处理集合的关键抽象概念,可对集合进行复杂的查找、过滤、筛选等操作。
流(Stream)的概念
流是数据渠道,用于操作数据源,所生成一种新的元素序列。集合讲的是数据,流讲的是计算是操作。
需要注意的是:
- Stream自身不会存储元素
- Stream不会改变数据源对象,相反会返回产生一个持有结果的新Stream
- Steam操作是延迟执行的,这意味着他们会等到需要结果的时候才执行。
流的操作步骤
- 创建Stream(获取一个数据源(集合,数组),从而获取一个流)
- 用Stream中间操作(一个中间操作链,用Stream API 对数据源数据进行操作处理)
- 终止Stream操作(终止操作,执行中间链操作,并产生结果)
常见操作代码示例
- 示例数据准备
@Data
class Student{
private String name;
private Integer age;
private String gender;
public Student() {
}
public Student(String name, Integer age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
List<Student> stuList = new ArrayList<>();
stuList.add(new Student("张三", 18, "男"));
stuList.add(new Student("李四", 28, "女"));
stuList.add(new Student("王五", 16, "男"));
stuList.add(new Student("赵六", 30, "女"));
stuList.add(new Student("孙七", 35, "女"));
stuList.add(new Student("周八", 55, "男"));
- 过滤 filter
Stream<Student> stuStream = stuList.stream().filter(i -> i.getAge() > 18);
stuStream.forEach(System.out::println);
// 也可简写成
stuList.stream().filter(i -> i.getAge() > 18).forEach(a->{
System.out.println(a.getName());
});
运算结果:
Student{name='李四', age=28, gender='女'}
Student{name='赵六', age=30, gender='女'}
Student{name='孙七', age=35, gender='女'}
Student{name='周八', age=55, gender='男'}
李四
赵六
孙七
周八
- limit 限定集合数量
stuList.stream().filter(i -> i.getAge() > 18).limit(2).forEach(a->{
System.out.println(a.getName());
});
运算结果:
李四
赵六
- skip 跳过元素
skip和limit可一起使用可做分页效果
stuList.stream().filter(i -> i.getAge() > 18).skip(2).limit(2).forEach(a->{
System.out.println(a.getName());
});
运算结果:
孙七
周八
- distinct 去重
distinct()去重需要重写实体类的hashCode()和equals()方法这里仅示例String集合去重
List<String> list2 = new ArrayList<>();
list2.add("中");
list2.add("人");
list2.add("中");
list2.add("去");
list2.stream().distinct().forEach(a->{
System.out.println(a);
});
运算结果:
中
人
去
- 排序 sorted
// 无参数排序
List<String> list2 = new ArrayList<>();
list2.add("e");
list2.add("c");
list2.add("b");
list2.add("z");
list2.stream().sorted().forEach(a->{
System.out.println(a);
});
// 有参数排序
stuList.stream().sorted((o1, o2) -> o2.getAge() - o1.getAge()).forEach(a->{
System.out.println(a.getName());
});
运算结果:
b
c
e
z
周八
孙七
赵六
李四
张三
王五
- count 返回流中个数
long count = stuList.stream().count();
8.max 返回最大值 min 返回最小值
// 按年龄大小正序找最大值
Optional<Student> max = stuList.parallelStream().max((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(max.get());
// 按年龄大小倒序找最大值
Optional<Student> max1 = stuList.parallelStream().max((o1, o2) -> o2.getAge() - o1.getAge());
System.out.println(max1.get());
// 按年龄大小正序找最小值
Optional<Student> max2 = stuList.parallelStream().min((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(max2.get());
// 按年龄大小倒序找最小值
Optional<Student> max3 = stuList.parallelStream().min((o1, o2) -> o2.getAge() - o1.getAge());
System.out.println(max3.get());
运算结果:
Student{name='周八', age=55, gender='男'}
Student{name='王五', age=16, gender='男'}
Student{name='王五', age=16, gender='男'}
Student{name='周八', age=55, gender='男'}
- collect 将流转换为其他形式
List<String> nameList = stuList.stream().map(Student::getName)
.collect(Collectors.toList());
nameList.forEach(System.out::println);
运算结果:
张三
李四
王五
赵六
孙七
周八
Stream API还有其他操作,这里仅记录工作中常用API操作。其他操作用到时再做添加。