2016-04-26 23 views
0

Hy jeder, Ich habe die Aufgabe, Java-Map in absteigender Reihenfolge der verschachtelten Array-Größe/Länge zu sortieren, aber das verschachtelte Array ist in verschachtelten Map. Die Struktur sieht so aus:Sortieren nach verschachtelten Array-Größe in verschachtelten Karte

HashMap<String, HashMap<String, ArrayList<String>>> classes = new HashMap<>(); 

I Lambda verwenden und ich versuchte, viele Varianten, einschließlich:

classes.entrySet().stream() 
      .sorted((k1, k2) -> Long.compare(classes.get(k2.getKey()).entrySet().stream().count(), classes.get(k1.getKey()).entrySet().stream().count())) 

und

classes.entrySet().stream() 
      .sorted((k1, k2) -> Integer.compare(k2.getValue().values().size(), k1.getValue().values().size())) 

aber ohne Erfolg. Aufgrund der Art der Daten kann ich keine andere Datenstruktur verwenden, ich muss bei dieser bleiben.

Irgendwelche Ideen, warum meine Sortierung fehlschlägt? Danke für jede Hilfe, ich weiß es zu schätzen.

+1

In welchem ​​Sinne ist es nicht die Art? –

+0

Die Sortierung gibt die Größe der verschachtelten Map anstelle der Array-Größe in der verschachtelten Map zurück. –

+0

Es gibt mehrere Arrays, die einem Schlüssel in der 'class's-Map zugeordnet sind.Sie müssen die Längenwerte aggregieren. Nach Durchschnitt, Summe, Median sortieren? Ihre Beispiele scheinen nach der Größe der Map zu sortieren, nicht nach der Größe der enthaltenen Arrays. – GuiSim

Antwort

0

Ihre Frage ist unterspezifiziert. Wenn die Werte Map sind, können Sie nicht einfach sagen, dass Sie nach der Größe ihrer Liste sortieren möchten, da es in jeder Map eine beliebige Anzahl von Listen geben kann. Ihr Beispiel in den Kommentaren erläutert nichts, da es dieses Problem überhaupt nicht behandelt. Wenn Sie davon ausgehen, dass die "Slave" -Karten immer eine Größe von eins haben, sollten Sie dies explizit angeben. Andernfalls müssen Sie die Größen aggregieren.

Weiter gibt es static Methoden in der Comparator Schnittstelle zum Erstellen eines Vergleichers basierend auf einer Eigenschaft des Elements zu vergleichen, damit Sie den Code nicht zweimal die Eigenschaft extrahieren müssen. kann aussehen wie

classes.entrySet().stream() 
    .sorted(Comparator.comparingInt(e -> e.getValue().values() 
              .stream().mapToInt(Collection::size).sum())) 
    .forEach(System.out::println); 

Hinweis

So ist die Lösung, die Größen der Listen Summieren, dass diese Aggregation funktioniert auch, wenn es nur eine Liste in jeder „Slave“ Karte ist.

nur vollständig zu sein, dass beachten Sie Map-Einträge speziell für die Sortierung gibt es Komparator Fabriken in der Map.Entry Schnittstelle, die

classes.entrySet().stream() 
    .sorted(Map.Entry.comparingByValue(Comparator.comparingInt(
     m -> m.values().stream().mapToInt(Collection::size).sum()))) 
    .forEach(System.out::println); 

wie verwendet werden kann, in diesem speziellen Fall, obwohl es keinen Vorteil bei der Verwendung ist. Aber wenn der Istwertkomparator einfacher ist, kann er den Code verbessern. Es gibt sogar eine parameterlose Variante (d. H. Map.Entry.comparingByValue()) für den einfachsten Fall, dass die Kartenwerte vergleichbar sind.

1

Hoffentlich sage ich nicht das Offensichtliche, aber angesichts der Informationen, die Sie angegeben haben, nehme ich an, dass Sie erwarten, .sorted() die ursprüngliche Sammlung zu sortieren.

Weil Sie Stream verwenden Die ursprüngliche Sammlung wird nicht geändert. .sorted() gibt eine neue Sammlung zurück. Verwenden Sie das Ergebnis davon.

+1

Nun, es wird einen sortierten "Stream" zurückgeben. Es muss immer noch in einer Sammlung gesammelt werden (die die Bestellung unterstützt). – Kayaman

+0

Ich sortiere die Map nur, um sie auf der Konsole zu drucken. Ich beabsichtige nicht, das Original irgendwie zu modifizieren. –

0

Dank Holger gelang es mir, die richtige Lösung mit etwas mehr experimentieren zu finden: Was für mich gearbeitet wurde

classes.entrySet().stream() 
      .sorted((k1, k2) -> Integer.compare(k2.getValue().values().stream() 
          .mapToInt(Collection::size).sum(), 
        k1.getValue().values().stream() 
          .mapToInt(Collection::size).sum())) 
Verwandte Themen