2016-01-30 6 views
10

Jak przekonwertować plik Map<String, Double> na List<Pair<String, Double>> w języku Java 8?Jak przekonwertować mapę na listę w języku Java 8

Napisałem tę realizację, ale to nie jest wydajne

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; 

wiem, że powinno to działa przy użyciu .collect(Collectors.someMethod()). Ale nie rozumiem, jak to zrobić.

Odpowiedz

16

Cóż, chcesz zebrać elementy Pair w List. Oznacza to, że musisz zamapować swoją Stream<Map.Entry<String, Double>> na Stream<Pair<String, Double>>.

Odbywa się to z operacją map:

Zwraca się strumień składający się z wynikiem stosowania daną funkcję elementów tego strumienia.

W tym przypadku, funkcja jest funkcją konwersji Map.Entry<String, Double> w Pair<String, Double>.

Wreszcie, chcesz je zebrać w List, abyśmy mogli użyć wbudowanego kolektora toList().

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()); 

Zauważ, że można zastąpić porównawczy Comparator.comparing(e -> -e.getValue()) przez Map.Entry.comparingByValue(Comparator.reverseOrder()).

+1

Należy zauważyć, że '-e.getValue()' nie zmienia kolejności NaN. W zleceniu forward zakłada się wartość 'Double.NaN' na końcu listy. Używając jednolity minus, wszystko zostanie odwrócone * z wyjątkiem * NaN: nadal będą na końcu listy. –

+0

Tak, 'Map.Entry.comparingByValue (Comparator.reverseOrder())' lub 'Collections.reverseOrder (Map.Entry.comparingByValue())'. Jeśli porównanie wartości ujemnych jest zamierzone [Tagir wyjaśnił różnicę] (http://stackoverflow.com/questions/35107550/how-to-convert-map-to-list-in-java-8 #comment57966768_35107595), a następnie "Komparator .comparingDouble' powinno być preferowane, aby uniknąć przepakowywania wartości. – Holger

5

Pamiętaj, że jeśli chcesz efektywne realizacji, należy wziąć pod uwagę to:

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())); 

Zakładam, że twoja klasa Pair mieć getSecond getter.

Przy pomocy kroku strumienia potoku utworzysz bufor pośredni, zapisz wszystko do tego bufora, przekształć go w tablicę, posortuj tę tablicę, a następnie zapisz wynik do ArrayList. Moje podejście, choć mniej funkcjonalne, przechowuje dane bezpośrednio do celu ArrayList, a następnie sortuje je w miejscu bez dodatkowego kopiowania. Moje rozwiązanie wymagałoby mniej czasu i pamięci pośredniej.