2016-01-30 21 views
10

Wie konvertiert man eine Map<String, Double> zu List<Pair<String, Double>> in Java 8?Wie konvertiert man Karte in eine Liste in Java 8

Ich schrieb diese Implementierung, aber es ist nicht effizient

Map<String, Double> implicitDataSum = new ConcurrentHashMap<>(); 
//.... 
List<Pair<String, Double>> mostRelevantTitles = new ArrayList<>(); 
implicitDataSum.entrySet().stream(). 
       .sorted(Comparator.comparing(e -> -e.getValue())) 
       .forEachOrdered(e -> mostRelevantTitles.add(new Pair<>(e.getKey(), e.getValue()))); 

return mostRelevantTitles; 

Ich weiß, dass es funktioniert .collect(Collectors.someMethod()) Verwendung sollte. Aber ich verstehe nicht, wie das geht.

Antwort

16

Nun, Sie möchten Pair Elemente in eine List sammeln. Das bedeutet, dass Sie Ihre Stream<Map.Entry<String, Double>> in eine Stream<Pair<String, Double>> mappen müssen.

Dies wird mit der map Operation durchgeführt:

Gibt einen Strom der Ergebnisse aus den Elementen dieses Stroms die gegebenen Funktion der Anwendung.

In diesem Fall wird die Funktion eine Funktion, um ein Map.Entry<String, Double> in eine Pair<String, Double> Umwandlung sein.

Schließlich möchten Sie das in eine List sammeln, so dass wir den eingebauten toList() Kollektor verwenden können.

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet() 
        .stream() 
        .sorted(Comparator.comparing(e -> -e.getValue())) 
        .map(e -> new Pair<>(e.getKey(), e.getValue())) 
        .collect(Collectors.toList()); 

Beachten Sie, dass der Komparator Comparator.comparing(e -> -e.getValue()) durch Map.Entry.comparingByValue(Comparator.reverseOrder()) ersetzen könnte.

+1

Beachten Sie, dass '-e.getValue()' NaNs nicht neu anordnet. Die Vorwärtsreihenfolge setzt voraus, dass am Ende der Liste "Double.NaN" -Werte vorhanden sind. Mit dem unären Minus werden Sie alles außer * NaNs rückgängig machen: sie werden immer noch am Ende der Liste sein. –

+0

Yeah, 'Map.Entry.comparingByValue (Comparator.reverseOrder())' oder 'Collections.reverseOrder (Map.Entry.comparingByValue())'. Wenn der Vergleich der negativen Werte beabsichtigt ist [Tagir erklärte den Unterschied] (http://stackoverflow.com/questions/35107550/how-to-convert-map-to-list-in-java-8#comment57966768_35107595), dann 'Comparator "cosparingDouble" sollte bevorzugt werden, um ein erneutes Speichern der Werte zu vermeiden. – Holger

5

Beachten Sie, dass, wenn Sie effiziente Implementierung möchten, sollten Sie dies berücksichtigen:

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet() 
        .stream() 
        .map(e -> new Pair<>(e.getKey(), e.getValue())) 
        .collect(Collectors.toList()); 
mostRelevantTitles.sort(Comparators.comparing(Pair::getSecond, Comparator.reverseOrder())); 

Ich gehe davon aus, dass Ihre Pair Klasse getSecond Getter haben.

Mit dem Stream-Pipeline-Schritt sorted() erstellen Sie Zwischenpuffer, speichern Sie alles in diesem Puffer, konvertieren Sie es in Array, sortieren Sie das Array, und speichern Sie das Ergebnis in ArrayList. Mein Ansatz, obwohl weniger funktional, speichert Daten direkt in das Ziel ArrayList, dann sortiert es in-Ort ohne zusätzliches Kopieren. Also würde meine Lösung weniger Zeit und Zwischenspeicher benötigen.

Verwandte Themen