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

时间:2019-06-21 20:26:27

标签: java list java-8 compare java-stream

我必须比较两个列表(list1到list2)上的元素,并且当这些元素与code属性的元素匹配时, 我必须替换为tobereplace属性的值。

我在list1中有

#define R "x"
const char* s = R"y"; // ill-formed raw string, not "x" "y"

在List2中,我有:

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

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

2 个答案:

答案 0 :(得分:1)

假设该类名为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的第一个匹配项的值。否则你什么都不做。
这段代码效率不高,但是对于小的列表来说却是完美的。
对于较大的列表,非常欢迎使用Map存储code/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;
                )

答案 1 :(得分:1)

只需将替换值保存在一个映射中(以代码作为键),然后遍历list1进行修改即可。

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在评论中指出的,如果list2包含重复值,则Collectors.toMap将引发异常。在这种情况下,OP并未真正指定要执行的操作,但解决方案是在Collectors.toMap中使用合并功能。

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

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

合并策略可以是任何内容,例如将第一个元素与非空值一起使用

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