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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35408435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:07:03  来源:igfitidea点击:

Iterate and Map two lists in java 8

java

提问by youssef Liouene

I have 2 lists:

我有 2 个列表:

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

Given the size of list1 is the same as list2

鉴于 list1 的大小与 list2 相同

I want to iterate ove the list2 and if the name2 of list2 is not null than update the name1 of list1.

我想遍历 list2,如果 list2 的 name2 不为空,则更新 list1 的 name1。

here is the code using old java:

这是使用旧Java的代码:

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

Which is the best way to implement this with java.util.stream?

使用 java.util.stream 实现这一点的最佳方法是什么?

回答by sprinter

Just to be clear, I think your code is intended to do the following: update the name of each item in list1to be the name of any item in list2that has the same ID. There doesn't seem to be anything checking if the names of items in list1are null.

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

If that's correct, then:

如果这是正确的,那么:

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

If you want to check if name is null, then add a new filter before setting the name:

如果要检查名称是否为空,则在设置名称之前添加一个新过滤器:

    .filter(Objects::isNull)

回答by Seelenvirtuose

As I mentioned in the comments. If the idis a uniqe identifier for your objects, then a Mapis more appropriate than a List.

正如我在评论中提到的。如果id是对象的唯一标识符,则 aMap比 a 更合适List

So you better work on such a map (assuming id is an integer):

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

Map<Integer, Object1> obj1map;

You could create that map from your first list with

您可以从第一个列表中创建该地图

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

Now you can stream over your second list and update the map accordingly:

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

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()));

回答by Seelenvirtuose

The idea of a stream is that it does nothave context. Knowing where you are in the first stream is context which you would need to find the corresponding item in the second stream.

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

Use a normal forloop with an index iinstead.

改用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;
  }
}