3 Stimmen

Auferlegung einer Gesamtordnung für alle Instanzen *jeder* Klasse in Java

Ich bin mir nicht sicher, ob der folgende Code alle in der Javadoc von Comparator genannten Bedingungen erfüllen 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 beliebigen Klasse eine Gesamtreihenfolge auferlegen, auch wenn diese Klasse Comparable nicht implementiert?

2voto

Cagatay Punkte 1342

Hey, seht mal, was ich gefunden habe!

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

Das ist genau das, wonach ich gesucht habe.

2voto

Damien B Punkte 1972

Hey, seht mal, was ich gefunden habe!

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

Ach ja, ich vergaß die IdentityHashMap (nur Java 6 und höher). Sie müssen nur aufpassen, wenn Sie Ihren Komparator freigeben.

1voto

Damien B Punkte 1972

Sie haben in Ihrem Kommentar geantwortet:

equals gab false zurück, aber der Identitäts-Hash-Code war derselbe, angenommen o1 == o2

Davon können Sie leider nicht ausgehen. In den meisten Fällen wird das funktionieren, aber in einigen Ausnahmefällen auch nicht. Und man kann nicht wissen, wann. Wenn ein solcher Fall eintritt, würde dies zum Beispiel zum Verlust von Instanzen in TreeSets führen.

1voto

Allain Lalonde Punkte 88365

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 equals in o1 abhängt, haben zwei Objekte, die logisch gleich sind (wie durch equals bestimmt), immer noch zwei unterschiedliche identityHashCodes.

Wenn sie also mit einem dritten Objekt (z) verglichen werden, könnten sie am Ende unterschiedliche Werte für compareTo ergeben.

Macht das Sinn?

1voto

nlucaroni Punkte 46744

Sie sollten wahrscheinlich eine Ausnahme auslösen, wenn es zu diesem letzten Punkt kommt return 0 Zeile - wenn eine Hash-Kollision auftritt. Ich habe eine Frage aber: Sie tun eine insgesamt Bestellung auf die Hashs, die ich denke, ist in Ordnung, aber sollte nicht einige Funktion übergeben werden, um eine lexikographische 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 von zwei ganzen Zahlen haben, die eine reelle Zahl bilden. Aber Sie werden nicht die richtige Reihenfolge bekommen, da Sie nur einen Hash des Objekts nehmen. Das bleibt Ihnen überlassen, wenn Sie Hashing gemeint haben, aber für mich macht das nicht viel Sinn.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X