Java - 如何根据多个属性删除ArrayList中的重复项
Java - How to Remove Duplicates in ArrayList Based on Multiple Properties
我想根据多个属性从数组列表中删除重复记录。这是一个示例域对象 class:
private String mdl;
private String ndc;
private String gpi;
private String labelName;
private int seqNo;
private String vendorName;
mdl、ndc、gpi、seqNo共同构成了一条唯一的记录。我想在检查这 4 个属性的数组列表中查找重复项,然后如果列表中已存在具有相同 4 个属性的记录,则从列表中删除该记录。
.equals()
和 .hashCode()
应该被覆盖以说明您的密钥:mdl、ndc。 gpi, 序列号在这个网站上有无数的指南可以做到这一点,但是像:
@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
。这将使您的代码更高效(没有重复项的情况下内存使用量更少)并且无需在之后搜索重复项。
您可以尝试执行以下操作;
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
方法中隐藏该逻辑要好得多。
我想根据多个属性从数组列表中删除重复记录。这是一个示例域对象 class:
private String mdl;
private String ndc;
private String gpi;
private String labelName;
private int seqNo;
private String vendorName;
mdl、ndc、gpi、seqNo共同构成了一条唯一的记录。我想在检查这 4 个属性的数组列表中查找重复项,然后如果列表中已存在具有相同 4 个属性的记录,则从列表中删除该记录。
.equals()
和 .hashCode()
应该被覆盖以说明您的密钥:mdl、ndc。 gpi, 序列号在这个网站上有无数的指南可以做到这一点,但是像:
@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
。这将使您的代码更高效(没有重复项的情况下内存使用量更少)并且无需在之后搜索重复项。
您可以尝试执行以下操作;
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
方法中隐藏该逻辑要好得多。