在java 8中迭代并映射两个列表

问题描述 投票:3回答:3

我有2个清单:

  1. List1:Object1(name1,id1)
  2. List2:Object2(name2,id2)

鉴于list1的大小与list2相同

我想迭代列表2,如果列表2的名称不是null,则更新list1的name1。

这是使用旧java的代码:

  for(Object1 obj1:list1) {
    for(Object2 obj2:list2) {
      if(obj1.getId1.equals(obj2.getId2)) {
        obj1.setName1(obj2.getName2);
      }
   }
}

哪个是用java.util.stream实现这个的最好方法?

java
3个回答
11
投票

为了清楚起见,我认为您的代码旨在执行以下操作:将list1中每个项目的名称更新为list2中具有相同ID的任何项目的名称。似乎没有任何检查list1中的项目名称是否为空。

如果这是正确的,那么:

list2.forEach(obj2 -> list1.stream()
     .filter(obj1 -> obj1.getId().equals(obj2.getId()))
     .forEach(obj1 -> obj1.setName(obj2.getName()));

如果要检查name是否为null,请在设置名称之前添加新过滤器:

    .filter(Objects::isNull)

3
投票

正如我在评论中提到的那样。如果id是你的对象的唯一标识符,那么MapList更合适。

所以你最好在这样的地图上工作(假设id是一个整数):

Map<Integer, Object1> obj1map;

您可以使用第一个列表创建该地图

obj1map = list1.stream().collect(toMap(Object1::getId, Function.identity()));

现在,您可以流式传输第二个列表并相应地更新地图:

list2
    .stream()
    .filter(o -> o.getName() != null) // remove null names
    .filter(o -> obj1map.containsKey(o.getId())) // just to make sure
    .forEach(o -> obj1map.get(o.getId()).setName(o.getName()));

-3
投票

流的想法是它没有上下文。知道您在第一个流中的位置是您需要在第二个流中找到相应项的上下文。

使用带有索引for的正常i循环。

for (int i=0; i < list2.size(); i++) {
  Object2 item2 = list2.get(i);
  if (list2.get(i).name != null) {
    list1.get(i).name = item.name;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.