使用Java 8查找一个列表中不在另一个列表中的元素

9

我有两个列表。要求根据条件从list1中过滤掉不在list2中的元素。

  Class Fighter
  {
    String name;
    String address;
  }     
  List<Fighter> pairs1 = new ArrayList();
    pairs1.add(new Fighter("a", "a"));
    pairs1.add(new Fighter("b", "a"));

    List<Fighter> pairs2 = new ArrayList();
    pairs2.add(new Fighter("a", "c"));
    pairs2.add(new Fighter("a", "d"));
    Set<Fighter> finalValues = new HashSet<>();


    finalValues = pairs1.stream().filter(firstList -> 
   pairs2.stream().noneMatch(secondList -> 
   firstList.getName().equals(secondList.getName())
            && firstList.getName().equals(secondList.getName()))).collect(Collectors.toSet());

    System.out.println(finalValues);

期望输出:a=a,b=a

解释:在 list1 中但不在 list2 中的元素

以上代码没有得到期望的输出。请告诉我如何更正上述流式代码以获得输出。


2
最简单的方法是实现一个包含属性的“equals”(与“hashcode”),然后在另一个列表中执行“contains”。此外,在当前上下文中,“noneMatch(secondList -> firstList.getName().equals(secondList.getName()) && firstList.getAddress().equals(secondList.getAddress()))”应该可以解决问题。 - Naman
1
请参见:https://dev59.com/7obca4cB1Zd3GeqPatPx - Stephen C
2个回答

6

首先在Fighter类中覆盖equals和hashcode方法。

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof Fighter))
        return false;
    Fighter f = (Fighter) o;
    return f.name.equals(name) && f.address.equals(address);
}

@Override
public int hashCode() {
    int result = name.hashCode();
    result = 31 * result + address.hashCode();
    return result;
}

然后从pairs2创建一个Set。最后使用其contains方法获取集合差异。下面是示例代码:

Set<Fighter> pairs2Set = new HashSet<>(pairs2);
Set<Fighter> setDiff = pairs1.stream()
    .filter(f -> !pairs2Set.contains(f))
    .collect(Collectors.toSet());

6

在过滤器中匹配时不使用地址。

List<Fighter> res = pairs1.stream()
                    .filter(f -> !pairs2.stream()
                                        .anyMatch(s -> f.getName().equals(s.getName())
                                                  && f.getAddress().equals(s.getAddress())))
                   .collect(Collectors.toList());

根据条件,在第一个列表中过滤包含在第二个列表中的元素。

更好的方法:

使用列表的contains方法

List<Fighter> res = pairs1.stream()
                            .filter(e -> !pairs2.contains(e)) 
                            .collect(Collectors.toList());

你需要在Fighter类中重写equals()方法。在使用contains()方法时,你将使用equals()方法来判断两个对象是否相同。

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof Fighter))
        return false;
    Fighter f = (Fighter) o;
    return f.name.equals(name) && f.address.equals(address);
}

但使用Set会更快。 参见类似使用Set解决问题的解决方案


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接