我有2个名单:
鉴于list1的大小与list2相同
我想迭代list2,如果list2的name2不为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实现此功能的最佳方法是什么?
答案 0 :(得分: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)
答案 1 :(得分:3)
正如我在评论中提到的那样。如果id
是对象的唯一标识符,那么Map
比List
更合适。
所以你最好在这样的地图上工作(假设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()));
答案 2 :(得分:-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;
}
}