2017-11-17 3 views
1

Ich habe ein Problem mit dem Sortieren einer ArrayList mit aufsteigender Reihenfolge. Ich verwende Comparator und Collator Of Collection-Klasse. Wie kann ich die erwartete Sortierreihenfolge erreichen? Hilfe wird sehr geschätzt.Sortierung von ArrayList mit Comparator in Java

aufsteigende Sortierung durch den Algorithmus berechnet wird:

[AutomationRejectNotification|,AutomationRejectNotification1011, AutomationRejectNotification1021,AutomationTestNotification1, AutomationTestNotification100,AutomationTestNotification2,testDisplay Template, Testing Chrome, Testing Field, Test Notfication, testnotif, Test Notification #1] 

Erwartete aufsteigende Sortierung Reihenfolge ist:

[AutomationRejectNotification1011, AutomationRejectNotification1021, AutomationRejectNotification|,AutomationTestNotification1, AutomationTestNotification2,AutomationTestNotification100,Test Notfication, Test Notification #1, testDisplay Template, Testing Chrome, Testing Field, testnotif] 

Java-Code:

public static void listSort(List<String> o1, boolean order) { 
     final Pattern p = Pattern.compile("^\\d+"); 
     Comparator<String> c = new Comparator<String>() { 
      public int compare(String object1, String object2) { 
       Collator collator = Collator.getInstance(Locale.US); 
       Matcher m = p.matcher(object1); 

       if (!m.find()) { 
        return collator.compare(object1, object2); 
       } else { 
        Long number2 = null; 
        Long number1 = Long.parseLong(m.group()); 

        m = p.matcher(object2); 
        if (!m.find()) { 
         return collator.compare(object1, object2); 
        } else { 

         number2 = Long.parseLong(m.group()); 

         int comparison = number1.compareTo(number2); 
         if (comparison != 0) { 
          return comparison; 
         } else { 
          return collator.compare(object1, object2); 
         } 
        } 
       } 


      } 
     }; 
     o1.sort(c); 
+0

So funktioniert Collator. Werfen Sie einen Blick auf diesen Artikel: https://documentation.progress.com/output/Corticon/5.3.2/suite_prototype/rfi1341263753418.html – WinterN

+0

Nein, @WinterN, es ist * nicht * wie 'Collator' funktioniert. Beachten Sie insbesondere, dass im US-Gebietsschema das '|' -Zeichen * nach * den Dezimalziffern steht, so dass "AutomationRejectNotification |" nach "AutomationRejectNotification1011" 'kollationiert, im Gegensatz zu der vom OP gemeldeten Reihenfolge. –

+0

@Kaps - können Sie anstelle eines einzigen Beispiels für Ihre erwartete Ausgabe die Sortierregel angeben, die für eine beliebige Eingabeliste gelten würde? –

Antwort

2

Ihre Comparator nicht richtig implementieren, den Vertrag von die Comparator Schnittstelle, also sind alle Wetten von f. Die compare() Methode muss alle diese Eigenschaften haben:

sgn(compare(x, y)) == -sgn(compare(y, x)) für alle x und y.

((compare(x, y)>0) && (compare(y, z)>0)) impliziert compare(x, z)>0.

compare(x, y)==0 impliziert, dass sgn(compare(x, z))==sgn(compare(y, z)) für alle z.

(API docs)

Wenn beide Zeichenketten eine nicht leere Dezimalziffer Sequenz enthalten, die verglichen werden, zu vergleichen Sie nur durch die Zahlen, während, wenn mindestens eine Zeichenkette ohne Ziffern ist dann über Sie vergleichen, der Zusammentrager. Dies führt zu folgenden Ergebnissen:

compare("z1", "y") > 0 

compare("y", "x3") > 0 

compare("z1", "x3") < 0 

, die nicht der zweiten geforderten Eigenschaft (Transitivität) entsprechen.

Möglicherweise möchten Sie die längsten führenden digitless Teilstrings als ein erstes Kriterium vergleichen, indem Sie alle Bindungen durch Vergleichen der nachfolgenden Zahlen, falls vorhanden, brechen. Das könnte wie folgt aussehen:

public static void listSort(List<String> o1, boolean order) { 
    final Pattern p = Pattern.compile("([^0-9]*)([0-9]+)?"); 
    final Collator collator = Collator.getInstance(Locale.US); 
    Comparator<String> c = new Comparator<String>() { 
     public int compare(String object1, String object2) { 
      Matcher m1 = p.matcher(object1); 
      Matcher m2 = p.matcher(object2); 

      if (!m1.lookingAt() || !m2.lookingAt()) { 
       assert false : "Should never happen"; 
      } 

      int result = collator.compare(m1.group(1), m2.group(1)); 

      if (result == 0) { 
       String digits1 = m1.group(2); 
       String digits2 = m2.group(2); 

       if (digits1 != null && digits2 != null) { 
        Long number1 = Long.valueOf(digits1); 
        Long number2 = Long.valueOf(digits2); 
        result = number1.compareTo(number2); 
       } else if (digits1 != null) { 
        result = 1; 
       } else if (digits2 != null) { 
        result = -1; 
       } 
      } 

      return result; 
     } 
    }; 
    o1.sort(c); 
} 

, die mit der erwarteten Reihenfolge übereinstimmen würden Sie präsentiert, aber es gibt auch andere Ordnungsschemata, die auch das gleiche Ergebnis für diese bestimmten Elemente erzeugen würden.

+0

Hi @John Bollinger: Danke für Ihre Eingaben. Es wirft unter Fehler .java.lang.NumberFormatException: Für Eingabezeichenfolge: "Test-AutomationTestNotification" bei java.lang.NumberFormatException.forInputString (NumberFormatException.java: 65) bei java.lang.Long.parseLong (Long.java:589) bei java.lang.Long.valueOf (Long.java:803) – kaps

+0

Ich habe alle Sonderzeichen in einigen der Testdaten. d. h. Testmotivation # 1, Testmotifcaiotn @ 34 – kaps

+0

@Kaps, ich vermute, Sie könnten dieses Problem selbst beheben, aber trotzdem habe ich es behoben. –

Verwandte Themen