Java

时间:2016-10-05 09:52:28

标签: java list collections

我有一个obj类型MyObj如下:

  class MyObj{
    String id;
    String username;
    String fullName;
    String age;

    //getters & setters
}

假设我们有2个包含不同数量元素的列表,如下所示:

List<MyObj> listA
List<MyObj> listB

我有一个通用方法可以检测listA中缺少的listB元素:

 public static <T> List<T> getListDifference(List<T> list1, List<T> list2) {
        Collection<T> first = new HashSet<T>(list1);
        Collection<T> second = new HashSet<T>(list2);
        first.removeAll(second);
        return new ArrayList<T>(first);
    }

如果来自listAlistB的对象对所有项目都有相同的字段,那么一切正常。

问题是某些项目只有idusername,但其他项目也可能有fullNameage,因此此方法不再有效。我想保持相同的逻辑,仅考虑id字段,因为它存在于所有对象中。

一种显而易见的方法是仅复制其他id中对象的List<String>字段,并使用获取的列表来检测元素,然后只按id从两个列表中搜索obj。由于多次迭代,此方法具有很大的复杂性。有没有简短的方法来实现这一目标?

3 个答案:

答案 0 :(得分:2)

您必须实施equalshashCode才能使用集合。集合需要一种识别一个对象是否等于另一个对象的方法,并且默认行为在这里不起作用。

顺便说一句,我建议在列表check this out.

上使用retainAll方法

答案 1 :(得分:2)

覆盖MyObjs equals方法:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    MyObj myObj = (MyObj) o;

    return (id != null ? !id.equals(myObj.id) : myObj.id != null);
}

IntelliJ / Android Studio有自动生成equalshashCode的帮助程序,您可以在其中选择必要的属性。

答案 2 :(得分:2)

正如@ Kevin Esche所提到的,你必须在equals() POJO中实施hashCode()MyObj,并根据你的情况,他们应该是:

   @Override
public int hashCode() {
    return Objects.hash(id);
}

@Override
public boolean equals(Object obj) {
    if (obj == this) return true;
    if (!(obj instanceof MyObj)) return false;

    MyObj myObj= (MyObj) obj;
    return Objects.equals(id, myObj.id);
}

即使年龄不同且ids相同,这也会有效。