5分钟上手Java8新特性Stream流的使用

1. 为什么使用Stream流操作?

Stream 作为 Java 8 的一大亮点,Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。

Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。

Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。

2. 实战准备

1. Entity的定义
  1. 我们使用lombok的 @Data 注解来解决pojo类的“样板式代码”,如getter,setter,equals方法等。
  2. 而@Builder注解的作用是启用创建者模式,也就是说在其他类中调用我们的Student类的时候使用 类名.builder()的方式构造对象,而不能直接声明构造对象。
import lombok.Builder;
import lombok.Data;
@Data
// 建造者模式创建对象
@Builder
public class Student {
    private Long id;
    private String name;
    private int age;
    private double score;
}
2. 建造者模式创建对象
  1. 我们使用Student.builder()新建对象,原因是为了创建复杂对象的算法,并且独立于该对象的组成部分以及它们的装配方式的设计模式。
  2. 我们构建了三个学生对象 分别是 小白 20岁 10.1分…
List<Student> resultList = new ArrayList<>();

resultList.add(Student.builder().id(1L).name("小白")age(20).score(10.1).build());
        
resultList.add(Student.builder().id(2L).name("小红").age(31).score(9.6).build());

resultList.add(Student.builder().id(3L).name("小黄").age(16).score(5.9).build());

3. 几种使用方法介绍

1. 根据某个属性进行筛选
  • 根据某个属性进行分组
List<String>nameList=list.stream().map(Student::getName).collect(Collectors.toList());
  • 可以看到我们将原本的对象集合List,使用map作为类型转换的工具,也就是 <Key,Value>的形式,对每个学生对象对应着一个年理进行分组,然后使用stream流的收集器collect将获得的map中的姓名元素作为一个List集合进行回收整理。
  • 得到结果如下
nameList:[小白, 小红, 小黄]
2. 根据某个属性进行筛选
List<Student> highCoreList = list.stream().filter(bean -> bean.getScore() > 5.0).collect(Collectors.toList());
  • 这里我们的操作是使用stream流操作中的filter进行条件过滤 ,bean作为我们要遍历筛选的对象的代表,不难看出我们这里的分数筛选条件是>5.9分,那么经过操作,我们可以得到List结果集如下。
highCoreList:[Student(id=1, name=小白, age=20,  score=10.1), Student(id=2, name=小红, age=31, score=9.6)]
3. 根据某个元素进行排序
List<Student> sortList = list.stream().sorted((a, b) -> b.getAge() - a.getAge()).collect(Collectors.toList());
  • 我们通过stream流中的sorted方法对对象根据年龄排序,若以sorted(a,b)为例,那么操作如下。
  • 逆序:使用b.getAge() - a.getAge()
  • 顺序:使用a.getAge() - b.getAge()

4. List转Map

Map<Long, Student> idMap = list.stream().collect(Collectors.toMap(Student::getId, bean -> bean));
  • 根据id为key,bean对应的对象为value 使用toMap方法进行转化,得到map<Long,Studeng>,得到输出结果如下。
idMap:{1=Student(id=1, name=小白, age=20, area=A, score=10.1), 
       2=Student(id=2, name=小红, age=31, area=A, score=9.6),
       3=Student(id=3, name=小黄, age=16, area=B, score=5.9), }

5. Map排序

Map<Long, Integer> idMap = list.stream().collect(Collectors.toMap(Student::getId, Studnet::getAge, (value1, value2) -> value1));


Map<Long, Integer> sortedKeyMap = idMap.entrySet().stream()
        .sorted(Map.Entry.<Long, Integer>comparingByKey().reversed())
        .collect(
                Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (oldVal, newVal) -> oldVal,
                        LinkedHashMap::new
                )
        );
  • 这里我们首先结局key重复元素的问题,我们可以看到,进行数据收集的时候,我们使用了id和age两个属性,那么我们使用 (value1, value2) -> value1),目的是 使用一个合并函数来决定如何合并相同key的值。
  • 其次,我们利用comparingByKey()达到按Key排序的目的,同理可知用comparingByValue进行按value排序。
  • 最后使用reversed()函数进行map内元素倒序。