我有一个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);
}
如果来自listA
和listB
的对象对所有项目都有相同的字段,那么一切正常。
问题是某些项目只有id
和username
,但其他项目也可能有fullName
或age
,因此此方法不再有效。我想保持相同的逻辑,仅考虑id
字段,因为它存在于所有对象中。
一种显而易见的方法是仅复制其他id
中对象的List<String>
字段,并使用获取的列表来检测元素,然后只按id
从两个列表中搜索obj。由于多次迭代,此方法具有很大的复杂性。有没有简短的方法来实现这一目标?
答案 0 :(得分:2)
您必须实施equals
和hashCode
才能使用集合。集合需要一种识别一个对象是否等于另一个对象的方法,并且默认行为在这里不起作用。
顺便说一句,我建议在列表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有自动生成equals
和hashCode
的帮助程序,您可以在其中选择必要的属性。
答案 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相同,这也会有效。