题
我不确定以下代码是否能确保 Comparator 的 Javadoc 中给出的所有条件。
class TotalOrder<T> implements Comparator<T> {
public boolean compare(T o1, T o2) {
if (o1 == o2 || equal(o1, o2)) return 0;
int h1 = System.identityHashCode(o1);
int h2 = System.identityHashCode(o2);
if (h1 != h2) {
return h1 < h2 ? -1 : 1;
}
// equals returned false but identity hash code was same, assume o1 == o2
return 0;
}
boolean equal(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
}
上面的代码是否会对任何类的所有实例强加总排序,即使该类没有实现 Comparable ?
解决方案
嘿,看看我发现了什么!
http://gafter.blogspot.com/2007/03/compact-object-comparator.html
哦,是的,我忘记了 IdentityHashMap(仅限 Java 6 及更高版本)。只需要注意释放比较器即可。
其他提示
您在评论中回答:
equals 返回 false 但身份哈希码相同,假设 o1 == o2
不幸的是你不能这样假设。大多数情况下,这会起作用,但在某些特殊情况下,它不会起作用。而且你不知道什么时候。当出现这种情况时,例如会导致 TreeSet 中的实例丢失。
我认为不会,因为不满足此条款:
最后,实现者必须确保对于所有 z,x.compareTo(y)==0 意味着 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。
由于 equal(o1, o2) 取决于 o1 的 equals 实现,因此逻辑上相等(由 equals 确定)的两个对象仍然具有两个不同的identityHashCode。
因此,当将它们与第三个对象 (z) 进行比较时,它们最终可能会产生不同的compareTo 值。
合理?
如果到达最后,您可能应该引发异常 return 0
行——当哈希冲突发生时。不过我确实有一个问题:您正在对哈希进行总排序,我认为这很好,但是不应该将某些函数传递给它来定义词典顺序吗?
int h1 = System.identityHashCode(o1);
int h2 = System.identityHashCode(o2);
if (h1 != h2) {
return h1 < h2 ? -1 : 1;
}
我可以想象您将对象作为形成实数的两个整数的元组。但你不会得到正确的顺序,因为你只获取对象的哈希值。如果散列是您的意思,这完全取决于您,但对我来说,这没有多大意义。
我同意这并不理想,因此发表评论。有什么建议么?
我认为现在有一种方法可以解决这个问题,因为您无法访问唯一可以区分两个实例的东西:他们在内存中的地址。所以我只有一个建议:重新考虑您对 Java 中通用总订购流程的需求:-)
我不太确定 System.identityHashCode(Object)
. 。差不多就是这样 == 是用来。您可能更想使用 Object.hashCode()
- 它更平行于 Object.equals(Object)
.