Java Collections Sortieren: Vergleich Methode verstösst gegen die Allgemeinen Vertrags
Ich weiß, es wurde gefragt und beantwortet Millionen von Zeiten, aber immer noch ich bin nicht in der Lage, herauszufinden, warum ich am Empfang mit der Verletzung beim Sortieren. Hier ist mein code:
Collections.sort(sorted, new Comparator<MyObject>() {
@Override
public int compare(MyObject m1, MyObject m2) {
//Actual energy comparison :-
//THE higher the energy, the earlier in the list
float delta = m1.getTotalEnergy() - m2.getTotalEnergy();
if (delta > 0) {
return 1;
} else if (delta < 0) {
return -1;
} else {
return 0;
}
}
});
und ich erhalte diese Fehlermeldung
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:895)
at java.util.TimSort.mergeAt(TimSort.java:512)
at java.util.TimSort.mergeForceCollapse(TimSort.java:453)
at java.util.TimSort.sort(TimSort.java:250)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
Irgendwelche Ideen ?
Bitte formatieren Sie den stacktrace
Andere threads ändern Sie den Wert von totalEnergy, während die Sortierung läuft?
mögliche Duplikate von "Comparison method violates its general contract!"
Sie könnten einfach verwenden: return Float.vergleichen(m1.getTotalEnergy(), m2.getTotalEnergy());
Ich habe kopiert diesen code und es macht seinen job ohne Probleme. Können Sie bitte zeigen Sie uns die input-Daten, und geben Sie die "sortiert" - Kollektion? Wie eine minimale reproduzierbare Beispiel?
Andere threads ändern Sie den Wert von totalEnergy, während die Sortierung läuft?
mögliche Duplikate von "Comparison method violates its general contract!"
Sie könnten einfach verwenden: return Float.vergleichen(m1.getTotalEnergy(), m2.getTotalEnergy());
Ich habe kopiert diesen code und es macht seinen job ohne Probleme. Können Sie bitte zeigen Sie uns die input-Daten, und geben Sie die "sortiert" - Kollektion? Wie eine minimale reproduzierbare Beispiel?
InformationsquelleAutor math_law | 2015-01-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vorausgesetzt
getTotalEnergy()
return(s)float
könnten SieMit
Float.valueOf(float)
ist wohl etwas effizienter, und dies ist hoffentlich leichter zu Lesen.Float.compareTo(Float)
mit autoboxing.Ja, aber wo im code ist die
return
? Hoffentlich nicht in dercompare()
.Vielleicht ist der code geschrieben werden kann, werden immer deutlicher. Dieser code sicher sieht aus wie es gibt eine floating-point-Zahl zu mir. This mehr Sinn macht.
Lieber
return Float.valueOf(m1.getTotalEnergy()).compareTo(m2.getTotalEnergy());
zu erlauben, es zu verwenden, dieFloat
aus dem cache, anstatt immer einen neuen zu erstellen.Bearbeitet. Ich hoffe, es ist leichter zu Lesen jetzt.
InformationsquelleAutor Elliott Frisch
Ohne Verweis auf
MyObject
. Meine Vermutung ist, dass der Komparator nicht mitMyObject.equal
.Ist, der Vertrag, die Sie verletzen wird:
Ihre Komparator vergleicht die Objekte mit der selben float-Wert als gleich, wo ein komplexer Komparator geben würde, eine Anordnung, während die equals-Methode würde sagen, die Objekte waren nicht gleich. Oder Sie hätten das umgekehrte problem -- die equals-Methode, sagt die Objekte gleich sind und die compare-Methode sagt, Sie sind anders.
Folgende arbeiten sollten.
danke , nach dem Versuch Atuos' Vorschlag mit Float.vergleichen ( hoffe, es Griffe NaNs) ich werde versuchen Ihren Vorschlag. BR.
Habe ich überprüft - NaN ' s sind nicht das Problem hier. Können Sie uns zeigen, MyObject.gleich und MyObject.hashCode bitte?
Ich habe diese Methoden nicht überschrieben. Alles, was ich liefern kann zusätzlich ?
Es könnte ein NaN. Ein Objekt wäre zu vergleichen anders, selbst wenn seine gesamte Energie war NaN, obwohl Sie gleich selbst.
InformationsquelleAutor Dunes
Vielleicht wird dies ändern:
InformationsquelleAutor roeygol
Folgende code ist getestet mit float, NaN und null-Werte. Alle Fälle korrekt behandelt werden. Ich erstellte eine
hashCode()
undequals()
Methode, um dieMyObject
Klasse.Ergebnis:
[null, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, NaN]
SortObjectFloatProperty
MyObject
InformationsquelleAutor Mr. Polywhirl
Gab es einige Diskussionen über
NaN
Werte in die Kommentare. Dies ist wichtig, weilNaN
verstößt gegen unsere typischen Erwartungen sind Vergleiche von floating point zahlen. Zum BeispielDouble.NaN > 0.0
undDouble.NaN < 1.0
beide falsch!Dadurch kann die Sortierung auf die Ausnahmen, wie Sie auftreten. Selbst wenn die exception nicht geworfen wird, kann es dazu führen, die Liste am Ende sortiert in der falschen Reihenfolge. Daher, Ihrer Art Komparator muss befassen sich mit
NaN
Werte. Zum Glück, die Bibliothek gebaut-Vergleiche wieDouble.compare()
dies für Sie tun. Dies hat die gleiche Semantik wieDouble.compareTo()
, außer, dass boxedDouble
Werte sind nicht notwendig. Finden Sie die Dokumentation für details. KurzNaN
Werte berücksichtigt, die größer als alle anderen Werte (einschließlich+Inf
), und negativ null ist weniger als positiv-null.Verwenden
Double.compare()
imComparator
fürsort
:Wenn Sie mit Java 8, Sie könnten dies tun:
Verarbeiten null-Werte, wickeln Sie die Komparator mit
nullsFirst
odernullsLast
:Immer noch die gleichen IAE? Versuchen Instrumentierung der Komparator, also drucken Sie (oder Protokoll), die Eingänge und das Ergebnis jedes Aufrufs, und dann schauen Sie auf den letzten Eintrag vor der immer die Ausnahme.
Wenn Sie Ihre Eingabe nicht haben, null-Werte, versuchen das einwickeln der Komparator mit
Comparator.nullFirst
oderComparator.nullsLast
(Java 8).Auch, hat
getTotalEnergy
immer wieder den gleichen Wert für jede gegebene Instanz vonMyObject
?InformationsquelleAutor Stuart Marks