Установить полный порядок для всех экземпляров * любого * класса в Java - PullRequest
3 голосов
/ 26 августа 2008

Я не уверен, будет ли следующий код обеспечивать все условия, указанные в Javadoc Comparator.

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 ]

2 голосов
/ 26 августа 2008

Эй, посмотри, что я нашел!

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

Это именно то, что я искал.

2 голосов
/ 26 августа 2008

Эй, посмотри, что я нашел!

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

О да, я забыл про IdentityHashMap (только Java 6 и выше). Просто нужно обратить внимание на выпуск вашего компаратора.

1 голос
/ 26 августа 2008

Вы, вероятно, должны вызвать исключение, если оно дойдет до этой последней строки return 0 - когда происходит коллизия хешей. У меня, правда, есть вопрос: вы делаете полное упорядочивание хешей, что, я думаю, хорошо, но не следует ли передать ему некоторую функцию для определения лексикографического порядка?

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

Я могу представить, что у вас есть объекты в виде кортежа из двух целых чисел, которые образуют действительное число. Но вы не получите правильный порядок, так как вы берете только хеш объекта. Это все зависит от вас, если вы имели в виду хеширование, но для меня это не имеет особого смысла.

1 голос
/ 26 августа 2008

Я не думаю, что это так, поскольку этот пункт не выполняется:

Наконец, разработчик должен убедиться, что x.compareTo (y) == 0 подразумевает, что sgn (x.compareTo (z)) == sgn (y.compareTo (z)) для всех z.

Поскольку значение равное (o1, o2) зависит от реализации равных в o1, два объекта, которые логически равны (как определено с помощью равных), по-прежнему имеют два разных identityHashCodes.

Таким образом, сравнивая их с третьим объектом (z), они могут получить разные значения для CompareTo.

Имеет смысл?

1 голос
/ 26 августа 2008

Вы ответили в своем комментарии:

равно возвращенному ложному, но хэш-код идентичности был тем же, предположим, что o1 == o2

К сожалению, вы не можете этого допустить. Большую часть времени это будет работать, но в некоторых исключительных случаях это не так. И ты не можешь знать когда. Когда такой случай появляется, это может привести к потере экземпляров в TreeSets, например.

0 голосов
/ 26 августа 2008

Я согласен, что это не идеально, поэтому комментарий. Есть предложения?

Я думаю, что теперь вы можете решить эту проблему, потому что вы не можете получить доступ к одной-единственной вещи, которая может различить два экземпляра: их адрес в памяти. Поэтому у меня есть только одно предложение: пересмотреть вашу потребность в общем процессе упорядочения в Java: -)

0 голосов
/ 26 августа 2008

Я не совсем уверен насчет System.identityHashCode(Object). Это почти то, для чего используется == . Возможно, вы захотите использовать Object.hashCode() - это больше параллельно Object.equals(Object).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...