当前位置: 首页 > 知识库问答 >
问题:

Java 8根据属性比较2个列表

蒋俊
2023-03-14

我必须比较两个list(清单1到清单2)上的元素,当这些元素与code属性的元素匹配时,我必须替换为tobereplace属性的值。

在清单1中,我有

[{code:"1", name:"first name", tobereplace: ""} , {code:"2", name:"first name1", tobereplace: ""}, 
{code:"3", name:"first name2", tobereplace: ""}, {code:"4", name:"first name3", tobereplace: ""}]

在清单2中,我有:

[{code:"1", name:"first name", tobereplace: ""} , {code:"2", name:"first name1", tobereplace: "" }, 
{code:"3", name:"first name2", tobereplace: ""}, {code:"4", name:"first name3", tobereplace: "this should come in list1"}]

理想情况下,List1应该具有list2的值;我们如何使用Java8流来实现这一点

共有2个答案

相旭
2023-03-14

只需将replace值保留在映射中(以代码为关键字),然后在清单1上迭代以在必要的地方进行修改。

Map<String, String> replaceValues = list2.stream()
    .collect(Collectors.toMap(x -> x.code, x -> x.tobereplace));
list1.stream
    .filter(x -> replaceValues.containsKey(x.code))
    .forEach(x -> x.tobereplace = replaceValues.get(x.code));

编辑

正如josejuan在注释中指出的,如果清单2包含重复的值,collectors.tomap将抛出异常。OP并没有真正指定在这种情况下要做什么,但解决方案是使用collectors.tomap中的合并函数。

这将使用它遇到的第一个元素与任何给定的代码:

Map<String, String> replaceValues = list2.stream()
    .collect(Collectors.toMap(x -> x.code, x -> x.tobereplace, (x1, x2) -> x1));

合并策略可以是任何东西,比如使用具有非空值的第一个元素,例如。

如果已知列表没有重复项,请使用集合而不是列表。它将使任何阅读代码的人都更加清楚,并帮助您避免不必要的检查。

阎安邦
2023-03-14

假设类名为foo,并且要更改的字段是带有getter/setter的String ValueTorePlace,您可以这样使用Listone.ReplaceAll():

list1.replaceAll(one ->  list2.stream()
                              .filter(other -> other.getCode().equals(one.getCode())
                              .findAny()
                              .map(Foo::getValueToReplace)
                              .ifPresent( newValue -> one.setValueToReplace(newValue));
                        return one;
                )

其思想是,对于list1的每个元素,您将其valueToreplace字段替换为list2第一个匹配项的值。否则,您将不执行任何操作。
此代码的效率不如它所能达到的效率,但对于较小的列表而言,它是完美的。
对于较大的列表,非常欢迎使用映射存储代码/ValueTorePlace

// supposing that the code are unique in each list
Map<Integer, String>  mapOfValueToReplaceByCode =
    list2.stream()
         .collect(toMap(Foo::getCode, Foo::getValueToReplace));

list1.replaceAll(one -> {
                 String newValue = mapOfValueToReplaceByCode.get(one.getCode());
                 if (newValue != null){ 
                     one.setValueToReplace(newValue);
                 }
                  return one;
                )
 类似资料:
  • 任务: null 我的示例的输出:

  • 是否可以在没有外部foreach的情况下迭代B。需要使用Java8在2个arays中标识公共值

  • 问题内容: 我需要比较2个不同数据库中的数据库表,以了解差异所在,是否有一个简单的工具或脚本来实现? 问题答案: redgate SQL数据比较

  • 要做到这一点,最干净的捷径是什么? 我知道它可以通过自定义比较器来实现。对于这种情况,难道没有现成的东西吗? 有点像这样:

  • 我想断言,相同类型的两个对象列表在该对象的属性值方面是相同的。例如,我有两个Person对象列表,它们具有名字、姓氏和中间名属性。每个Person对象都有这些属性(java bean)的方法setter和getter,构造函数不包含任何参数。 让我们假设这里已经有一个名为existingPersonList的两个人的列表,该列表具有以下属性: 现有人员1:firstName=鲍勃,lastName

  • 假设我有一个双人课 我希望对它进行排序,首先是第一个值,然后是第二个值。现在,如果我这样做 一切都很好,列表按对的第一个值排序,但如果我这样做 它因错误而失败 好吧,所以它可能无法推断参数,所以如果我这样做 它因错误而失败 为什么它适用于comparing()而不适用于comparing()。然后比较()?