Imponha uma ordem total em todas as instâncias de *qualquer* classe em Java

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

  •  09-06-2019
  •  | 
  •  

Pergunta

Não tenho certeza se o código a seguir garantiria todas as condições fornecidas no Javadoc do 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);
    }
}

O código acima imporá uma ordem total em todas as instâncias de qualquer classe, mesmo que essa classe não implemente Comparable?

Foi útil?

Solução

Ei, olha o que eu encontrei!

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

Ah, sim, esqueci do IdentityHashMap (apenas Java 6 e superior).Basta prestar atenção na divulgação do seu comparador.

Outras dicas

Ei, olha o que eu encontrei!

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

Isso é exatamente o que eu estava procurando.

Você respondeu em seu comentário:

igual retornou falso, mas o código hash de identidade era o mesmo, suponha que o1 == o2

Infelizmente você não pode presumir isso.Na maioria das vezes isso vai funcionar, mas em alguns casos excepcionais, não.E você não pode saber quando.Quando tal caso aparecesse, isso levaria à perda de instâncias em TreeSets, por exemplo.

Acho que não, pois esta cláusula não é atendida:

Finalmente, o implementador deve garantir que x.compareTo(y)==0 implica que sgn(x.compareTo(z)) == sgn(y.compareTo(z)), para todos z.

Como equal(o1, o2) depende da implementação de equals de o1, dois objetos que são logicamente iguais (conforme determinado por equals) ainda possuem dois IdentityHashCodes diferentes.

Portanto, ao compará-los com um terceiro objeto (z), eles podem acabar gerando valores diferentes para compareTo.

Faz sentido?

Você provavelmente deveria gerar uma exceção se chegar ao último return 0 line --quando ocorre uma colisão de hash.Eu tenho uma pergunta:você está fazendo uma ordenação total do hash, o que eu acho que é bom, mas alguma função não deveria ser passada para ele para definir uma ordem lexicográfica?

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

Posso imaginar que você tenha os objetos como uma tupla de dois inteiros que formam um número real.Mas você não obterá a ordem adequada, pois estará apenas obtendo um hash do objeto.Tudo depende de você se hash é o que você quis dizer, mas para mim não faz muito sentido.

Concordo que isso não é o ideal, daí o comentário.Alguma sugestão?

Acho que agora existe uma maneira de resolver isso, porque você não pode acessar a única coisa que pode distinguir duas instâncias:seu endereço na memória.Então só tenho uma sugestão:reconsidere sua necessidade de ter um processo geral de pedido total em Java :-)

Eu não tenho certeza sobre o System.identityHashCode(Object).Isso é basicamente o que == é usado para.Você pode preferir usar o Object.hashCode() - está mais em paralelo com Object.equals(Object).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top