2017-02-27 2 views
4

Ich möchte eine Map <String, Integer> von List<String> in Java 8, so etwas konvertieren:Java Liste <String> to Map <String, Integer> convertion

Map<String, Integer> namesMap = names.stream().collect(Collectors.toMap(name -> name, 0)); 

weil ich eine Liste von Strings haben, und ich würde Ich mag es, eine Map zu erstellen, wobei der Schlüssel die Zeichenfolge der Liste ist und der Wert Integer (eine Null) ist.

Mein Ziel ist es, die Elemente der String-Liste (später in meinem Code) zu zählen.

Ich weiß, dass es einfach ist, es auf die "alte" Weise umzuwandeln;

Map<String,Integer> namesMap = new HasMap<>(); 
for(String str: names) { 
    map1.put(str, 0); 
} 

aber ich frage mich, es gibt auch eine Java 8-Lösung.

+7

gerade Änderung '0' auf 'Name -> 0': 'Map namesMap = names.stream(). collect (Collectors.toMap (name -> name, name -> 0)); 'aber dies schlägt fehl, wenn du Duplikate hast. Wenn Sie Vorkommen zählen wollen, machen Sie das zuerst einmal richtig: 'Map namesMap = names.stream(). Collect (Collectors.groupingBy (Name -> Name, Collectors.counting()));' Statt 'name -> name' können Sie auch' Function.identity() 'verwenden. – Holger

+0

Ohh es funktioniert, danke! :) – LakiGeri

Antwort

6

Wie bereits erwähnt, die Parameter zu Collectors.toMap haben Funktionen, so dass Sie 0-name -> 0 ändern (können Sie alle nutzen anderer Parametername anstelle von name).

Beachten Sie jedoch, dass dies fehlschlägt, wenn in names Duplikate vorhanden sind, da dies zu doppelten Schlüsseln in der resultierenden Karte führt. Um dies zu beheben, Rohr konnte man den Strom durch Stream.distinct zuerst:

Map<String, Integer> namesMap = names.stream().distinct() 
            .collect(Collectors.toMap(s -> s, s -> 0)); 

Oder initialisieren nicht alle diese Standardeinstellungen, und verwenden getOrDefault oder computeIfAbsent statt:

int x = namesMap.getOrDefault(someName, 0); 
int y = namesMap.computeIfAbsent(someName, s -> 0); 

Oder, wenn Sie möchten, erhalten die Zählungen der Namen, können Sie einfach Collectors.groupingBy und Collectors.counting verwenden:

Map<String, Long> counts = names.stream().collect(
     Collectors.groupingBy(s -> s, Collectors.counting())); 
5

Der Collector toMap empfängt zwei Mapper - einen für den Schlüssel und einen für den Wert. Der Schlüssel-Mapper könnte einfach den Wert aus der Liste zurückgeben (d. H. Entweder 10, wie Sie derzeit haben, oder einfach den eingebauten Function.Identity verwenden). Der Wert Mapper sollte einfach den ausgehartcodierte Wert von 0 für jeden Schlüssel:

namesMap = 
    names.stream().collect(Collectors.toMap(Function.identity(), name -> 0)); 
+2

Ist 'Integer' nicht genau der (IMHO eher schlecht gewählte) Name des Parameters zum Lambda hier? –

+0

@Eugene guter Punkt auch. Bearbeitet und behoben. Es macht den Code definitiv sauberer. – Mureinik

Verwandte Themen