3

我不确定以下代码是否能确保 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?

4

7 答案 7

2

嘿,看看我发现了什么!

http://gafter.blogspot.com/2007/03/compact-object-comparator.html

这正是我一直在寻找的。

于 2008-08-26T16:03:27.633 回答
2

嘿,看看我发现了什么!

http://gafter.blogspot.com/2007/03/compact-object-comparator.html

哦,是的,我忘记了 IdentityHashMap(仅限 Java 6 及更高版本)。只需要注意释放比较器即可。

于 2008-08-26T16:08:54.250 回答
1

您在评论中回答:

equals 返回 false 但身份哈希码相同,假设 o1 == o2

不幸的是,你不能假设。大多数时候这会起作用,但在某些特殊情况下,它不会。你不知道什么时候。当这种情况出现时,例如会导致 TreeSets 中的实例丢失。

于 2008-08-26T15:20:55.053 回答
1

我不认为它这样做,因为这个条款没有得到满足:

最后,实施者必须确保对于所有 z,x.compareTo(y)==0 意味着 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。

由于 equal(o1, o2) 依赖于 o1 的 equals 实现,因此逻辑上相等(由 equals 确定)的两个对象仍然有两个不同的 identityHashCode。

因此,当将它们与第三个对象 (z) 进行比较时,它们最终可能会为 compareTo 产生不同的值。

有道理?

于 2008-08-26T15:32:28.317 回答
1

return 0如果它到达最后一行 - 当发生哈希冲突时,您可能应该引发异常。不过我确实有一个问题:您正在对哈希进行总排序,我想这很好,但不应该将某些函数传递给它来定义字典顺序吗?

    int h1 = System.identityHashCode(o1);
    int h2 = System.identityHashCode(o2);
    if (h1 != h2) {
        return h1 < h2 ? -1 : 1;
    }

我可以想象你将对象作为两个整数组成的元组,形成一个实数。但是您不会得到正确的排序,因为您只获取对象的哈希值。如果散列是您的意思,这完全取决于您,但对我来说,这没有多大意义。

于 2008-08-26T15:44:56.633 回答
0

我不太确定System.identityHashCode(Object). 这几乎就是==的用途。您可能更愿意使用Object.hashCode()- 它与Object.equals(Object).

于 2008-08-26T15:35:07.047 回答
0

我同意这并不理想,因此发表评论。有什么建议么?

我认为现在有办法解决这个问题,因为你无法访问唯一可以区分两个实例的东西:它们在内存中的地址。所以我只有一个建议:重新考虑您是否需要在 Java 中进行一般的总订购流程 :-)

于 2008-08-26T15:51:19.550 回答