在Java中对* any *类的所有实例强加总排序

时间:2008-08-26 15:11:27

标签: java algorithm

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

7 个答案:

答案 0 :(得分:2)

嘿,看看我找到了什么!

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

这正是我所寻找的。

答案 1 :(得分:2)

  嘿,看看我找到了什么!

     

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

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

答案 2 :(得分:1)

你在评论中回答:

  

等于返回false但标识哈希码相同,假设为o1 == o2

不幸的是你无法想象。大部分时间都会起作用,但在某些例外情况下,它不会。你什么时候都不知道。出现这种情况时,例如,它会导致在TreeSet中丢失实例。

答案 3 :(得分:1)

我不认为这样做,因为没有达到这个条款:

  

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

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

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

有意义吗?

答案 4 :(得分:1)

当发生哈希冲突时,如果它到达最后return 0行,则应该引发异常。我确实有一个问题:你在哈希上做了一个总排序,我猜这很好,但是不应该传递一些函数来定义一个Lexicographical命令吗?

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

  

我同意这不是理想的,因此评论。有什么建议吗?

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