2016-08-17 2 views
1

ich viele mögliche Lösung im Netz gegeben versucht habe, wie Systemeigenschaft zu setzen und in Doppel zu konvertieren, aber immer noch gleiche Fehler:Erste Fehler: Vergleichsmethode gegen seinen allgemeinen Vertrag

java.lang.IllegalArgumentException: Comparison method violates its general contract! 
    at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:835) 
    at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:453) 
    at java.util.ComparableTimSort.mergeForceCollapse(ComparableTimSort.java:392) 
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:191) 
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:146) 
    at java.util.Arrays.sort(Arrays.java:472) 
    at java.util.Collections.sort(Collections.java:155) 

Hier bin mein Code:

 System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 
     Collections.sort(docs, new Comparator<FeedDocument>() { 
      public int compare(FeedDocument o1, FeedDocument o2) { 

       int year1 = 0; 
       int year2 = 0; 
       int returnResult = 0; 
       if (o1.containsKey(FeedConstants.PUBLICATION_YEAR) 
         && o2.containsKey(FeedConstants.PUBLICATION_YEAR) 
         && o1.get(FeedConstants.PUBLICATION_YEAR) != null 
         && (o1.get(FeedConstants.PUBLICATION_YEAR) instanceof String) 
         && o2.get(FeedConstants.PUBLICATION_YEAR) != null 
         && (o2.get(FeedConstants.PUBLICATION_YEAR) instanceof String)) { 

        String firstyear = (String) o1.get((FeedConstants.PUBLICATION_YEAR)); 
        String secondyear = (String) o2.get((FeedConstants.PUBLICATION_YEAR)); 

        if (firstyear.equals(secondyear)) { 
         return 0; 
        } else if (firstyear != null && !firstyear.isEmpty() && secondyear != null 
          && !secondyear.isEmpty()) { 

         year1 = Integer.parseInt(firstyear.trim()); 

         year2 = Integer.parseInt(secondyear.trim()); 

         // int result = year2 - year1; 
         // if (result > 0) { 
         // returnResult = 1; 
         // } else if (result < 0) { 
         // returnResult = -1; 
         // } 
         return Double.compare(year2, year1); 
        } 

       } else { 
        returnResult = 0; 
       } 
       return returnResult; 
      } 
     }); 
+1

Mögliches Duplikat von ["Vergleichsmethode verstößt gegen den allgemeinen Vertrag!"] (Http://stackoverflow.com/questions/8327514/comparison-method-violates-its-general-contract) – bradimus

+0

Nur FYI 'instanceof' gibt 'false' zurück 'Wenn das linke Argument null ist, ist keine erneute Überprüfung erforderlich. Ja – mszymborski

+0

, können Sie kombinieren 'o1.containsKey (FeedConstants.PUBLICATION_YEAR) && o1.get (FeedConstants.PUBLICATION_YEAR)! = Null && o1.get (FeedConstants.PUBLICATION_YEAR) instanceof String' in einfach' o1.get (FeedConstants.PUBLICATION_YEAR) instanceof Zeichenfolge'. Sie haben auch zusätzliche unnötige Kontrollen auf die Straße: 'firstear! = Null' und' secondyear! = Null'. Diese verwirren den Code und machen es schwerer zu folgen. – mapeters

Antwort

0

Edward Peters' answer korrekt ist Ihr Problem bei der Diagnose, als compare Methode nicht konsistent (transitiv) Ergebnisse.

Der beste Weg, so etwas wie die folgenden in Ihrem compare Methode, dies zu lösen ist:

if (o1.get(FeedConstants.PUBLICATION_YEAR) instanceof String) { 
    if (o2.get(FeedConstants.PUBLICATION_YEAR) instanceof String) { 
     // Perform the comparison here like you are 
    } else { 
     /* 
     * This could also be 1, the key is to have it consistent 
     * so the final sorted list clearly separates the FeedDocuments 
     * with a String PUBLICATION_YEAR and those without one. 
     */ 
     return -1; 
    } 
} else if (o2.get(FeedConstants.PUBLICATION_YEAR) instanceof String) { 
    /* 
    * In this case, o1 doesn't have a String PUBLICATION_YEAR and o2 
    * does, so this needs to be the opposite of the return value 
    * 6 lines up to be consistent. 
    */ 
    return 1; 
} else { 
    /* 
     * Consider all FeedDocuments without a String PUBLICATION_YEAR 
     * to be equivalent, otherwise you could do some other comparison 
     * on them here if you wanted. 
     */ 
    return 0; 
} 

Der Schlüssel ist, wenn Sie kümmern mit einem String um eine Teilmenge der Liste sortiert werden (die FeedDocument s nur Veröffentlichungsjahr, dann müssen Sie sie zuerst von dem Rest der Liste trennen, die Sie nicht sortierten sortierten (indem Sie entweder 1 oder -1 zurückgeben, wenn eins der FeedDocument s ein String Veröffentlichungsjahr hat und das andere nicht Dann können Sie die gewünschte Teilmenge ohne inkonsistente Ergebnisse sortieren

+0

Ich habe nicht verstanden/* * In diesem Fall hat o1 keinen String PUBLICATION_YEAR und o2 *, so dass dies das Gegenteil des Rückgabewerts * 6 Linien sein muss, um konsistent zu sein. */ –

+0

@TanuGarg an der Zeile "return -1" haben wir festgestellt, dass "o1" ein Veröffentlichungsjahr hat und "o2" nicht. Also, 'return -1' sagt, dass' o1' (und alle 'FeedDocument's mit einem Publikationsjahr) vor denen stehen sollten, die kein Veröffentlichungsjahr haben. In der Zeile "return 1" haben wir festgestellt, dass "o1" kein Erscheinungsjahr hat, aber "o2", was das umgekehrte Szenario des ersten ist. Wenn also "return 1" zurückgegeben wird, wird 'o1' (und alle' FeedDocument's ohne Veröffentlichungsjahr) nach denen mit einem Veröffentlichungsjahr eingefügt, was dem entspricht, was in der Zeile "return -1" passiert ist. – mapeters

+1

Verstanden. Danke für die Erklärung auch Fehler wurde behoben. –

4

Ziemlich sicher, dass ich weiß, was hier los ist ...

Suppse:

Dann

:

compare (o1, o2); //returns 0 
compare (o2, o3); //returns 0 
compare (o1, o3); //returns not 0 

Sie sind also behauptet o1 == o2 == o3 aber o1 != o3

+0

Wie löst man? Bitte schlagen Sie vor, –

+0

@TanuGarg Sie müssen es nur so machen, dass ein einzelner Nullwert keine Gleichheit zurückgibt. Der Standard, den ich im Allgemeinen verwende, ist "Wenn sie beide null sind, sind sie gleich, wenn eins null ist, ist es automatisch kleiner, wenn beide null sind, vergleiche normal." –

+0

Danke Edward. Fehler behoben. –

Verwandte Themen