Erzwingen Sie eine Gesamtreihenfolge für alle Instanzen *jeder* Klasse in Java

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

  •  09-06-2019
  •  | 
  •  

Frage

Ich bin mir nicht sicher, ob der folgende Code alle im Javadoc von Comparator angegebenen Bedingungen gewährleisten würde.

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);
    }
}

Wird der obige Code allen Instanzen einer Klasse eine Gesamtreihenfolge auferlegen, auch wenn diese Klasse Comparable nicht implementiert?

War es hilfreich?

Lösung

Hey, schau dir an, was ich gefunden habe!

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

Oh ja, ich habe die IdentityHashMap vergessen (nur Java 6 und höher).Sie müssen nur darauf achten, Ihren Komparator freizugeben.

Andere Tipps

Hey, schau dir an, was ich gefunden habe!

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

Das ist genau das, was ich gesucht habe.

Sie haben in Ihrem Kommentar geantwortet:

„equals“ hat „false“ zurückgegeben, aber der Identitäts-Hash-Code war derselbe. Nehmen wir an, o1 == o2

Davon kann man leider nicht ausgehen.Meistens wird das funktionieren, in einigen Ausnahmefällen jedoch nicht.Und Sie können nicht wissen, wann.Wenn ein solcher Fall auftritt, würde dies beispielsweise zum Verlust von Instanzen in TreeSets führen.

Ich glaube nicht, dass dies der Fall ist, da diese Klausel nicht erfüllt ist:

Schließlich muss der Implementierer sicherstellen, dass x.compareTo(y)==0 impliziert, dass sgn(x.compareTo(z)) == sgn(y.compareTo(z)) für alle z.

Da equal(o1, o2) von der Implementierung von equal durch o1 abhängt, haben zwei Objekte, die logisch gleich sind (wie durch equal bestimmt), immer noch zwei unterschiedliche IdentityHashCodes.

Wenn man sie also mit einem dritten Objekt (z) vergleicht, ergeben sie möglicherweise unterschiedliche Werte für „compareTo“.

Sinn ergeben?

Wenn es so weit kommt, sollten Sie wahrscheinlich eine Ausnahme auslösen return 0 Zeile – wenn eine Hash-Kollision auftritt.Ich habe allerdings eine Frage:Sie führen eine vollständige Sortierung der Hashs durch, was meiner Meinung nach in Ordnung ist, aber sollte ihm nicht eine Funktion übergeben werden, um eine lexikografische Reihenfolge zu definieren?

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

Ich kann mir vorstellen, dass Sie die Objekte als Tupel zweier Ganzzahlen haben, die eine reelle Zahl bilden.Sie erhalten jedoch nicht die richtige Reihenfolge, da Sie nur einen Hash des Objekts verwenden.Es liegt ganz bei Ihnen, ob Hashing das ist, was Sie meinen, aber für mich ergibt das nicht viel Sinn.

Ich stimme zu, dass dies nicht ideal ist, daher der Kommentar.Irgendwelche Vorschläge?

Ich denke, es gibt jetzt eine Möglichkeit, das zu lösen, da Sie nicht auf die eine und einzige Sache zugreifen können, die zwei Instanzen unterscheiden kann:ihre Adresse im Gedächtnis.Daher habe ich nur einen Vorschlag:Überdenken Sie Ihre Notwendigkeit eines allgemeinen Gesamtbestellvorgangs in Java :-)

Da bin ich mir nicht wirklich sicher System.identityHashCode(Object).Das ist so ziemlich das, was die == wird verwendet für.Vielleicht möchten Sie lieber das verwenden Object.hashCode() - es ist eher parallel zu Object.equals(Object).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top