Imponer un orden total en todas las instancias de *cualquier* clase en Java

StackOverflow https://stackoverflow.com/questions/28301

  •  09-06-2019
  •  | 
  •  

Pregunta

No estoy seguro de si el siguiente código garantizaría todas las condiciones indicadas en el Javadoc de 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);
    }
}

¿Impondrá el código anterior un orden total en todas las instancias de cualquier clase, incluso si esa clase no implementa Comparable?

¿Fue útil?

Solución

¡Oye, mira lo que encontré!

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

Oh, sí, me olvidé de IdentityHashMap (solo Java 6 y superior).Sólo tienes que prestar atención al liberar tu comparador.

Otros consejos

¡Oye, mira lo que encontré!

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

Esto es exactamente lo que estaba buscando.

Respondiste en tu comentario:

igual devolvió falso pero el código hash de identidad era el mismo, supongamos o1 == o2

Desafortunadamente no puedes asumir eso.La mayoría de las veces eso funcionará, pero en algunos casos excepcionales, no funcionará.Y no puedes saber cuándo.Cuando aparece un caso así, se perderían instancias en TreeSets, por ejemplo.

No creo que sea así ya que no se cumple esta cláusula:

Finalmente, el implementador debe asegurarse de que x.compareTo(y)==0 implique que sgn(x.compareTo(z)) == sgn(y.compareTo(z)), para todo z.

Dado que igual (o1, o2) depende de la implementación de iguales por parte de o1, dos objetos que son lógicamente iguales (según lo determinado por iguales) todavía tienen dos identidades HashCodes diferentes.

Entonces, al compararlos con un tercer objeto (z), podrían terminar arrojando valores diferentes para compareTo.

¿Tener sentido?

Probablemente deberías plantear una excepción si llega al último return 0 línea: cuando ocurre una colisión de hash.Aunque tengo una pregunta:estás haciendo un pedido total de los hash, lo cual supongo que está bien, pero ¿no debería pasarse alguna función para definir un orden lexicográfico?

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

Me imagino que tienes los objetos como una tupla de dos números enteros que forman un número real.Pero no obtendrás el orden adecuado ya que solo estás tomando un hash del objeto.Todo esto depende de usted si lo que quería decir es hash, pero para mí, no tiene mucho sentido.

Estoy de acuerdo en que esto no es ideal, de ahí el comentario.¿Alguna sugerencia?

Creo que ahora hay una manera de resolver eso, porque no puedes acceder a la única cosa que puede distinguir dos instancias:su dirección en la memoria.Entonces solo tengo una sugerencia:reconsidere su necesidad de tener un proceso de pedido total general en Java :-)

No estoy realmente seguro acerca de System.identityHashCode(Object).Eso es más o menos lo que == se utiliza para.Quizás prefieras utilizar el Object.hashCode() - es más en paralelo con Object.equals(Object).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top