写点什么

Java8 Stream 中如何对集合数据进行快速匹配和赋值

作者:Java你猿哥
  • 2023-03-28
    湖南
  • 本文字数:3178 字

    阅读完需:约 10 分钟

Java8 Stream中如何对集合数据进行快速匹配和赋值

开幕先看代码

List<Hero> heroes = StreamListDemo01.heroValues();List<Salarys> salarysValues = StreamListDemo01.salarysValues();for (Hero hero : heroes) {     if (salarysValues.size()>0) {       for (Salarys salarysValue : salarysValues) {         if (hero.getId()==salarysValue.getId()) {               hero.setSalary(salarysValue.getSalary());               break;          }         hero.setSalary(0.0F);         }    }else{      hero.setSalary(0.0F);        }   }
复制代码

需求是这个样子的

是要为一个 Hero 集合中的每个对象,赋予一个匹配的 Salarys 对象中的 salary 值。具体实现方式为遍历 Hero 集合,对于每一个 Hero 对象,遍历 Salarys 集合,只有当 Hero 对象的 ID 与 Salarys 对象的 ID 匹配时,才将 Salarys 对象的 salary 值赋值给 Hero 的 salary 属性。如果 Hero 的 ID 没有匹配成功,则将 Hero 的 salary 属性设置为 0.0F。如果 Salarys 集合为空,则将 Hero 的 salary 属性设置为 0.0F。

虽然通过嵌套 for 搞定了,但是我想把这玩意搞成 Java8 Stream 写法的!接下让我们开始看逐步拆解吧。

思路概述

  1. 将 heroes 转换为 Stream 对象;

  2. 使用 peek 操作设置所有 hero 的初始 salary 为 0;

  3. 对 heroes 进行 forEach 操作,对于每个 hero,将 salarysValues 转换为 Stream 对象;

  4. 使用 filter 操作筛选出符合条件的 salary(即 id 匹配);

  5. 使用 findFirst 操作获取第一个匹配结果(如果有的话);

  6. 如果有匹配结果,则使用 ifPresent 操作将 salary 的值赋给该 hero 的 salary 属性。若无匹配结果,则 salary 仍为初始值 0。

步骤详解

  1. 将 heroes 转换为 Stream 对象

将 heroes 集合对象转换为 Stream 对象,可以使用以下方式:

heroes.stream()
复制代码
  1. 使用 peek 操作设置所有 hero 的初始 salary 为 0

使用 peek 方法来实现操作了,peek 方法会遍历集合中的每一个元素,可以对每个元素进行操作并返回一个 Stream 对象。

.peek(hero -> hero.setSalary(0.0F))
复制代码
  1. 对 heroes 进行 forEach 操作,对于每个 hero,将 salarysValues 转换为 Stream 对象

在 forEach 方法中对每个 hero 进行操作,对于每个 hero,需要将另一个集合 salarysValues 转换为 Stream 对象,可以使用以下操作:

.forEach(hero -> {    salarysValues.stream()
复制代码
  1. 使用 filter 操作筛选出符合条件的 salary(即 id 匹配)

对于 salarysValues 集合中元素的筛选,需要通过 filter 操作进行筛选。filter 方法返回一个 Stream,由于我们只需要一个结果,因此使用 findFirst 方法获取第一个结果。

.filter(salary -> hero.getId() == salary.getId())
复制代码

该代码会对 salarysValues 集合中的每个元素进行比较操作,将符合条件的元素返回作为一个新的 Stream,只有符合条件的元素才会继续执行下面的操作。使用 lambda 表达式的方式,将当前 hero 的 id 和 salarysValues 集合中的 id 进行比较,如果相同,则返回 true。

  1. 使用 findFirst 操作获取第一个匹配结果(如果有的话)

使用 findFirst 方法获取第一个匹配的结果,如果有分配的 Salary,则第一个匹配结果应该是分配到该 Hero 的 Salary。findFirst 方法返回一个 Optional 对象,Optional 封装了要返回对象可能为空的情况。

.findFirst()
复制代码
  1. 如果有匹配结果,则使用 ifPresent 操作将 salary 的值赋给该 hero 的 salary 属性。若无匹配结果,则 salary 仍为初始值 0。

使用 ifPresent 方法,如果结果不为空(存在匹配结果),就将结果设置给该 Hero 的 Salary,如果不存在匹配结果,则该 Hero 的 Salary 属性值不被改变,即为初始值 0。

.ifPresent(salary -> hero.setSalary(salary.getSalary()));hero.setSalary(0.0F); // 设置Hero的薪水属性初始值为0
复制代码

完整 stream 代码示例:

heroes.stream()    .peek(hero -> hero.setSalary(0.0F)) // 设置所有hero的初始salary为0    .forEach(hero -> {        salarysValues.stream()            .filter(salary -> hero.getId() == salary.getId()) // 筛选出符合条件的salary            .findFirst() // 获取第一个匹配结果(如果存在)            .ifPresent(salary -> hero.setSalary(salary.getSalary())); // 将匹配到的salary的值赋给hero        hero.setSalary(0.0F); // 如果不存在匹配结果,设置薪水初始值为0    });
复制代码

完整示例代码


public class StreamListDemo01 {
private static List<Hero> heroValues(){ List<Hero> heroes = new ArrayList<>(); for (int i = 1; i < 10; i++) { Hero hero = new Hero(); hero.setId(i); hero.setName("张三"+i); heroes.add(hero); } return heroes; }
private static List<Salarys> salarysValues(){ List<Salarys> salarysList = new ArrayList<>(); for (int i = 1; i < 5; i++) { Salarys salarys = new Salarys(); salarys.setId(i); salarys.setSalary(1.4F+i); salarysList.add(salarys); } return salarysList; }
public static void main(String[] args) { List<Hero> heroes = StreamListDemo01.heroValues(); List<Salarys> salarysValues = StreamListDemo01.salarysValues();
for (Hero hero : heroes) { if (salarysValues.size()>0) { for (Salarys salarysValue : salarysValues) { if (hero.getId()==salarysValue.getId()) { hero.setSalary(salarysValue.getSalary()); break; } hero.setSalary(0.0F); } }else{ hero.setSalary(0.0F); } }
heroes.stream() .peek(hero -> hero.setSalary(0.0F)) // 设置所有hero的初始salary为0 .forEach(hero -> { salarysValues.stream() .filter(salary -> hero.getId() == salary.getId()) .findFirst() .ifPresent(salary -> hero.setSalary(salary.getSalary())); // 将匹配到的salary的值赋给hero }); System.out.println(heroes); }}
class Hero{ private String Name; private int Id; private Float Salary;
public String getName() { return Name; }
public void setName(String name) { Name = name; }
public int getId() { return Id; }
public void setId(int id) { Id = id; }
public Float getSalary() { return Salary; }
public void setSalary(Float salary) { Salary = salary; }
@Override public String toString() { return "Hero{" + "Name='" + Name + '\'' + ", Id=" + Id + ", Salary=" + Salary + '}'; }}

class Salarys{ private int Id; private Float Salary;
public int getId() { return Id; }
public void setId(int id) { Id = id; }
public Float getSalary() { return Salary; }
public void setSalary(Float salary) { Salary = salary; }
@Override public String toString() { return "Salarys{" + "Id=" + Id + ", Salary=" + Salary + '}'; }}
复制代码


用户头像

Java你猿哥

关注

一只在编程路上渐行渐远的程序猿 2023-03-09 加入

关注我,了解更多Java、架构、Spring等知识

评论

发布
暂无评论
Java8 Stream中如何对集合数据进行快速匹配和赋值_Java_Java你猿哥_InfoQ写作社区