我想基于多个属性从arraylist中删除重复的记录。这是一个示例域对象类:
private String mdl;
private String ndc;
private String gpi;
private String labelName;
private int seqNo;
private String vendorName;
mdl,ndc,gpi和seqNo共同构成唯一的记录。我想在检查这4个属性的arraylist中找到重复项,然后如果列表中已经存在具有相同4个属性的记录,则将该记录从列表中删除。
答案 0 :(得分:4)
.equals()
和.hashCode()
应该被覆盖以说明您的密钥:mdl,ndc。 gpi,seqNo。在此站点上有无数的指南来执行此操作,但是类似:
@Override
public boolean equals(Object obj) {
if(obj != null && obj instanceof MyClass) {
MyClass o = (MyClass)obj;
return mdl.equals(o.mdl) && ndc.equals(o.ndc) &&
gpi.equals(o.gpi) && seqNo == o.seqNo;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(mdl, ndc, gpi, seqNo);
}
如果担心的话,可能会有更有效的实现方法。
然后,您可以使用以下方法将列表转换为集合:
Set<MyClass> set = new HashSet<>(list);
结果set
将没有任何重复,现在您可以根据需要用新值list = new ArrayList<>(set);
替换列表。
如果要保持原始列表中项目的顺序,请实例化LinkedHashSet
而不是HashSet
。
与您的直接问题无关,如果首先要避免重复,则可以考虑使用Set
而不是List
。它将使您的代码更高效(没有重复项的情况下更少的内存使用),并且无需在以后搜索重复项。
答案 1 :(得分:1)
您可以尝试执行以下操作;
List<Obj> list = ...; // list contains multiple objects
Collection<Obj> nonDuplicateCollection = list.stream()
.collect(Collectors.toMap(Obj::generateUniqueKey, Function.identity(), (a, b) -> a))
.values();
(a, b) -> a
,表示当两个对象相同时,最终映射将包含较早的对象,而后一个将被丢弃,如果需要后一个对象,则可以更改此行为。
Obj
在哪里;
public static class Obj {
private String mdl;
private String ndc;
private String gpi;
private String labelName;
private int seqNo;
private String vendorName;
// other getter/setters
public String generateUniqueKey() {
return mdl + ndc + gpi + seqNo;
}
}
我宁愿做这样的事情,而不是覆盖hashCode
或equals
方法,这在默认状态下的另一种逻辑中可能是必需的……另外还明确显示了如何声明像generateUniqueKey
这样的适当方法的唯一性比将某些逻辑隐藏在某些hashCode
方法中要好得多,就可读性和可维护性而言。