有一个List<MyElement> = new ArrayList<MyElement>();
class MyElement {
private Object[] values;
//...
}
我需要在此列表中找到所有唯一条目。我会使用HashSet
,但问题是values
可能包含null
AND 应该假设null
等于任何其他值。例如,Object[] o1 = new Object[]{1,null,"s2"}
和Object[] o2 = new Object[]{1,2,"s2"}
应被视为相同的条目(即非唯一),其中只有一个应保留在HashSet
中。有没有办法在HashSet中覆盖正确的函数?
答案 0 :(得分:1)
你真的需要O(1)时间add()和contains()吗?我看不到为你的MyElement类编写一个满足你需求的hashCode()函数的好方法。
然而,比较器(或制作MyElement Comparable)可以解决问题,然后您可以使用TreeSet找出列表中的唯一元素。这是第一次尝试(你不应该按原样使用它,它可能不起作用)。
class MyElementComparator implements Comparator<MyElement> {
@Override
public int compare(MyElement e, MyElement f) {
int sizeCmp = e.values.length - f.values.length;
if(sizeCmp != 0) // Lists are of different sizes, elements aren't equal
return sizeCmp;
// Start comparing element by element
for(int i=0; i<e.values.length; i++) {
Object eo = e.values[i];
Object fo = f.values[i];
// Null is a wildcard
if(eo == null || fo == null)
continue;
// If objects are the same, then continue too.
if(eo == fo || eo.equals(fo))
continue;
// Otherwise, decide on one object or the other based on hashcode (or any other valid mean).
return eo.hashCode() - fo.hashCode();
}
// All elements were equal or skipped, then the objects are equal.
return 0;
}
}
快速测试似乎表明它有效:
MyElement a = new MyElement(1, null, "s2");
MyElement b = new MyElement(1, 2, "s2");
MyElement c = new MyElement(null, "s", 3);
TreeSet<MyElement> set = new TreeSet<MyElement>(new MyElementComparator());
set.add(a);
set.add(b);
set.add(c);
System.out.println(set.size()); // 2
但如果你向set添加一个等于另外两个不同元素的元素,那么事情就会失败。例如{1}和{2}是不同的,但如果添加{null},则该集应该减少为{null},这不会发生。
没有比较者会实现这一点,你需要另一种数据结构,也许是一个不相交的集合(Union Find)? http://en.wikipedia.org/wiki/Disjoint-set_data_structure
答案 1 :(得分:1)
您的问题是空引用不应该等于任何内容,因为equals contract表示:
对于任何非空引用值x,x.equals(null)应返回false。
因此,如果您的values
字段对您的equals
实施有意义,那么您无法在不违反合同的情况下实施您所说的内容。
我会将Object[]
字段替换为List
字段,并在MyElement
类中实现等号。这将为列表as its contract states提供有意义的等于。当然,如果你重写equals,你也应该覆盖hashcode以保持事物的一致性。
我要保持优秀的旧HashSet
不受影响,请记住,写下正确的藏品不是一项微不足道的任务,无论乍一看多么容易。因此,覆盖您的MyElement
哈希码并等于方法以满足您的需求而不会破坏这两个契约。