开幕先看代码
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 写法的!接下让我们开始看逐步拆解吧。
思路概述
将 heroes 转换为 Stream 对象;
使用 peek 操作设置所有 hero 的初始 salary 为 0;
对 heroes 进行 forEach 操作,对于每个 hero,将 salarysValues 转换为 Stream 对象;
使用 filter 操作筛选出符合条件的 salary(即 id 匹配);
使用 findFirst 操作获取第一个匹配结果(如果有的话);
如果有匹配结果,则使用 ifPresent 操作将 salary 的值赋给该 hero 的 salary 属性。若无匹配结果,则 salary 仍为初始值 0。
步骤详解
将 heroes 转换为 Stream 对象
将 heroes 集合对象转换为 Stream 对象,可以使用以下方式:
使用 peek 操作设置所有 hero 的初始 salary 为 0
使用 peek 方法来实现操作了,peek 方法会遍历集合中的每一个元素,可以对每个元素进行操作并返回一个 Stream 对象。
.peek(hero -> hero.setSalary(0.0F))
复制代码
对 heroes 进行 forEach 操作,对于每个 hero,将 salarysValues 转换为 Stream 对象
在 forEach 方法中对每个 hero 进行操作,对于每个 hero,需要将另一个集合 salarysValues 转换为 Stream 对象,可以使用以下操作:
.forEach(hero -> { salarysValues.stream()
复制代码
使用 filter 操作筛选出符合条件的 salary(即 id 匹配)
对于 salarysValues 集合中元素的筛选,需要通过 filter 操作进行筛选。filter 方法返回一个 Stream,由于我们只需要一个结果,因此使用 findFirst 方法获取第一个结果。
.filter(salary -> hero.getId() == salary.getId())
复制代码
该代码会对 salarysValues 集合中的每个元素进行比较操作,将符合条件的元素返回作为一个新的 Stream,只有符合条件的元素才会继续执行下面的操作。使用 lambda 表达式的方式,将当前 hero 的 id 和 salarysValues 集合中的 id 进行比较,如果相同,则返回 true。
使用 findFirst 操作获取第一个匹配结果(如果有的话)
使用 findFirst 方法获取第一个匹配的结果,如果有分配的 Salary,则第一个匹配结果应该是分配到该 Hero 的 Salary。findFirst 方法返回一个 Optional 对象,Optional 封装了要返回对象可能为空的情况。
如果有匹配结果,则使用 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 + '}'; }}
复制代码
评论