我有一个List人员,我想查找重复的条目,以约束除以外的所有字段id。因此,请使用equals()-method(并因此使用List.contains()),因为它们已考虑id在内。
List
id
equals()
List.contains()
public class Person { private String firstname, lastname; private int age; private long id; }
修改equals()和hashCode()方法以忽略该id字段不是一种选择,因为代码的其他部分依赖于此。
hashCode()
如果我想忽略该id字段,Java中最有效的方法是对重复项进行分类?
构建一个Comparator<Person>以实现您的自然键排序,然后使用基于二进制搜索的重复数据删除。TreeSet即可为您提供这种能力。
Comparator<Person>
TreeSet
请注意,Comparator<T>.compare(a, b)必须满足通常的反对称性,传递性,一致性和反射性要求,否则二进制搜索顺序将失败。您还应该使它感知空值(例如,一个,另一个或两者的名字段为空)。
Comparator<T>.compare(a, b)
您的Person类的一个简单的自然键比较器如下(它是静态成员类,如果每个字段都有访问器,则没有显示)。
public class Person { public static class NkComparator implements Comparator<Person> { public int compare(Person p1, Person p2) { if (p1 == null || p2 == null) throw new NullPointerException(); if (p1 == p2) return 0; int i = nullSafeCompareTo(p1.firstname, p2.firstname); if (i != 0) return i; i = nullSafeCompareTo(p1.lastname, p2.lastname); if (i != 0) return i; return p1.age - p2.age; } private static int nullSafeCompareTo(String s1, String s2) { return (s1 == null) ? (s2 == null) ? 0 : -1 : (s2 == null) ? 1 : s1.compareTo(s2); } } private String firstname, lastname; private int age; private long id; }
然后,您可以使用它来生成唯一列表。使用仅当元素在集合中不存在时才add返回的方法true:
add
true
List<Person> newList = new ArrayList<Person>(); TreeSet<Person> nkIndex = new TreeSet<Person>(new Person.NkComparator()); for (Person p : originalList) if (nkIndex.add(p)) newList.add(p); // to generate a unique list
或交换该行的最后一行以输出重复项
if (nkIndex.add(p)) newList.add(p);
无论您做什么,都不要remove在枚举原始列表时使用它,这就是为什么这些方法将您的独特元素添加到新列表中的原因。
remove
如果您只对唯一列表感兴趣,并希望使用尽可能少的行:
TreeSet<Person> set = new TreeSet<Person>(new Person.NkComparator()); set.addAll(originalList); List<Person> newList = new ArrayList<Person>(set);