2016-06-20 5 views
0

Ich habe überall nach einer Lösung suchen, aber nicht schaffen, eine zu finden, die funktioniert.Android Joda Zeit, Probleme beim Sortieren von Zeichenfolgen von ISOPeriodFormat

Ich habe ein "Scoreboard", das die höchsten "Zeiten" (Zeitraum zwischen zwei Zeitpunkten) zeigen muss, die die App mit Joda Time berechnet hat.

Alle Strings werden in einer ArrayList gespeichert und über einen ArrayAdapter und eine ListView angezeigt.

Das Problem: Collections.sort scheint nicht einmal mit ISO-Format ordnungsgemäß zu funktionieren.

Ich bin die Zeit mit dem Format zu speichern:

PeriodFormatter formatter = ISOPeriodFormat.standard(); 

Welche diese gibt aus: "PT1M15.664S" (1 min 15 Sekunden)

Dass ich in einen String umwandeln und speichern in die ArrayListe.

Wie kann ich diese Strings so sortieren, dass sie von der längsten zur kürzesten Zeit in meinem Scoreboard gehen?

Ich habe versucht, natürliche Sortierung und Alphanum Comparator ohne Glück. Jedes Mal, sie eine Kappe geht (Minuten, Stunden, Tage) die Werte wie diese:

"PT2.455S" 
"PT1.324S" 
"PT1M15.333S" 

Statt dessen, was Ich mag würde:

"PT1M15.333S" 
"PT2.455S" 
"PT1.324S" 

Mit Collection.sort (myArrayList) nicht arbeite entweder.

Irgendeine Idee, was ich tun sollte?

Mein Code:

// set is a set<String> retrieving it's values from a stringset scores saved 
in the sharedpreferences of the app 

set = sharedPreferences.getStringSet("scores", null); 

//scores is the ArrayList 
scores.clear(); 


    if (set != null){ 

     scores.addAll(set); 

    }else{ 

     scores.add("No Time Yet!"); 
     set = new LinkedHashSet<String>(); 
     set.addAll(scores); 
     sharedPreferences.edit().putStringSet("scores",set).apply(); 
    } 

//removing the String No Time Yet because it no longer serves a purpose here 
    if ((set != null)&& (set.size()>1)){ 
     scores.remove("No Time Yet!"); 
    } 


    arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,scores); 

listView.setAdapter(arrayAdapter); 

Collections.sort(scores); 

Vielen Dank für Ihre Zeit.

+0

Idee: Nicht auf die Zeichenfolge-Werte sortieren. Sortieren Sie die Joda-Punkte * vor *, um sie in Strings umzuwandeln. – Andreas

+1

Natürlich müssen Sie zuerst die Sortierreihenfolge definieren, z. ist 'P30DT2H' mehr oder weniger als' P1M'? Ist 'PT23H30M' mehr oder weniger als' P1D'? Wenn Sie die Sommerzeit beobachten, lautet die Antwort * weniger *, außer an einem Tag im Jahr, an dem es * mehr * ist. Ähnlich sind "PT24H" und "P1D" gleich, mit Ausnahme von 2 Tagen pro Jahr. – Andreas

+0

Es wäre eine gute Idee, aber ich kann nicht Zeiten als Teil der gemeinsamen Preferences in Android speichern (ich bekomme die Werte von einer anderen Aktivität), so dass ich mit dem String-Set stecken. – William

Antwort

1

Kurze Antwort: Verwenden Sie die Klasse Duration, nicht Period.

Erläuterung:

Ihr allgemeiner Ansatz mit der Klasse Period ist falsch. Dieser Typ repräsentiert ein Tupel von verschiedenen Mengeneinheitspaaren. Einige von ihnen sind nicht umwandelbar oder vergleichbar. Zum Beispiel ist es unmöglich zu bestimmen, ob P30D größer oder gleich oder kleiner als P1M ist (denke an Februar, April oder August). So ist es ziemlich klar, warum Sie nicht nach Perioden resp. Warum implementiert diese Klasse nicht die Schnittstelle Comparable. Dieser Einwand gilt sowohl für die Objekte vom Typ Period als auch für deren kanonische ISO-Darstellung (als String).

Aber da du

die höchste „Zeiten“ (Zeitraum zwischen zwei Zeitpunkten) wollen

Sie können Duration verwenden, um die absolute Menge der verstrichenen Sekunden und Millisekunden zwischen zwei vorgegebenen Zeitpunkten zu bestimmen. Dieser Typ ist vergleichbar und hat nur zwei kleinere Einschränkungen, die für Sie wahrscheinlich nicht von Bedeutung sind:

  • Präzision Millisekunden begrenzt
  • ignoriert Schaltsekunden

Ich empfehle Dauer Objekte zu vergleichen, nicht Strings, weil Sie wollen eine chronologische Reihenfolge, keine lexikographische Reihenfolge. So könnte man die String-Darstellung von Duration (wie PT72.345S) zur Speicherung verwenden, aber es zum Vergleich analysieren:

Instant i1 = new Instant(0); 
Instant i2 = new Instant(72_345); 
Duration d1 = new Duration(i1, i2); 

Instant i3 = new Instant(60_000); 
Instant i4 = new Instant(200_710); 
Duration d2 = new Duration(i3, i4); 

List<String> scoreTimes = new ArrayList<>(); 
scoreTimes.add(d1.toString()); 
scoreTimes.add(d2.toString()); 

// order from longest times to shortest times 
Collections.sort(
    scoreTimes, 
    new Comparator<String>() { 

     @Override 
     public int compare(String s1, String s2) { 
      return Duration.parse(s2).compareTo(Duration.parse(s1)); 
     } 
    } 
); 

System.out.println(scoreTimes); // [PT140.710S, PT72.345S] 
+0

Vielen Dank für die Erklärung so gut. Ich verstehe jetzt, warum das, was ich tat, nicht funktionierte. Ich habe dein Beispiel verfolgt und alles funktioniert gut! – William

Verwandte Themen