2016-01-30 13 views
10

Come convertire un Map<String, Double> in List<Pair<String, Double>> in Java 8?Come convertire la mappa in elenco in Java 8

Ho scritto questa implementazione, ma non è efficace

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; 

So che dovrebbe lavori utilizzando .collect(Collectors.someMethod()). Ma non capisco come farlo.

risposta

16

Bene, si desidera raccogliere gli elementi Pair in un List. Ciò significa che devi mappare il tuo Stream<Map.Entry<String, Double>> in un Stream<Pair<String, Double>>.

Ciò viene fatto con il funzionamento map:

restituisce un flusso costituito dai risultati dell'applicazione della funzione data agli elementi di questo flusso.

In questo caso, la funzione sarà una funzione di conversione un Map.Entry<String, Double> in un Pair<String, Double>.

Infine, desideri raccoglierlo in un List, in modo che possiamo utilizzare il collector integrato 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()); 

Si noti che è possibile sostituire il comparatore Comparator.comparing(e -> -e.getValue()) da Map.Entry.comparingByValue(Comparator.reverseOrder()).

+1

Si noti che '-e.getValue()' non riordina i NaN. L'ordine in avanti presuppone avere valori 'Double.NaN' alla fine dell'elenco. Usando meno unario annullerai tutto * tranne * NaN: saranno ancora alla fine della lista. –

+0

Sì, 'Map.Entry.comparingByValue (Comparator.reverseOrder())' o 'Collections.reverseOrder (Map.Entry.comparingByValue())'. Se si confrontano i valori negativi è inteso [Tagir ha spiegato la differenza] (http://stackoverflow.com/questions/35107550/how-to-convert-map-to-list-in-java-8#comment57966768_35107595), quindi 'Comparator .comparingDouble' dovrebbe essere preferito per evitare il reinserimento dei valori. – Holger

5

Si noti che se si desidera efficiente implementazione, si dovrebbe prendere in considerazione questo:

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

Presumo che la classe Pair hanno getSecond getter.

Utilizzando il passo gasdotto sorted() flusso di creare buffer di intermedio, memorizzare tutto a tale buffer, convertirlo in una matrice, ordinare tale matrice, quindi memorizzare il risultato nel ArrayList. Il mio approccio, sebbene meno funzionale, memorizza i dati direttamente nel target ArrayList, quindi li ordina direttamente senza alcuna copia aggiuntiva. Quindi la mia soluzione richiederebbe meno tempo e una memoria intermedia.

Problemi correlati