Ich möchte eine Liste von Objekten mit den Streams und Lambdas von Java 8 in eine Map übersetzen.
So würde ich es in Java 7 und darunter schreiben.
private Map<String, Choice> nameMap(List<Choice> choices) {
final Map<String, Choice> hashMap = new HashMap<>();
for (final Choice choice : choices) {
hashMap.put(choice.getName(), choice);
}
return hashMap;
}
Ich kann dies leicht mit Java 8 und Guava erreichen, aber ich würde gerne wissen, wie man dies ohne Guava macht.
In Guave:
private Map<String, Choice> nameMap(List<Choice> choices) {
return Maps.uniqueIndex(choices, new Function<Choice, String>() {
@Override
public String apply(final Choice input) {
return input.getName();
}
});
}
Und Guave mit Java 8 Lambdas.
private Map<String, Choice> nameMap(List<Choice> choices) {
return Maps.uniqueIndex(choices, Choice::getName);
}
java
lambda
java-8
java-stream
Tom Cammann
quelle
quelle
Maps.uniqueIndex(choices, Choice::getName)
.Seq
aus der JOOL- Bibliothek (die ich jedem empfehlen würde, der Java 8 verwendet) können Sie die Kürze auch verbessern mit:seq(choices).toMap(Choice::getName)
it -> it
mich tatsächlich .Function.identity()
wird hier hauptsächlich verwendet, weil es in der Dokumentation verwendet wird, auf die verwiesen wird, und das war alles, was ich zum Zeitpunkt des Schreibens über Lambdas wussteWenn nicht garantiert wird, dass Ihr Schlüssel für alle Elemente in der Liste eindeutig ist, sollten Sie ihn in a
Map<String, List<Choice>>
anstelle von a konvertierenMap<String, Choice>
quelle
Multimaps
eine bessere Option? Dies kann eine Unannehmlichkeit sein, da keinMap
Objekt zurückgegeben wird.Verwenden Sie
getName()
als Schlüssel und sichChoice
selbst als Wert der Karte:quelle
Collectors.toMap(Choice::getName,c->c)
(2 Zeichen kürzer)choices.stream().collect(Collectors.toMap(choice -> choice.getName(),choice -> choice));
Erste Funktion für Schlüssel, zweite Funktion für Wertc -> c
aber es enthältFunction.identity()
mehr semantische Informationen. Ich benutze normalerweise einen statischen Import, damit ich nur verwenden kannidentity()
Hier ist eine weitere für den Fall, dass Sie Collectors.toMap () nicht verwenden möchten.
quelle
Collectors.toMap()
oder unsere eigene HashMap, wie Sie im obigen Beispiel gezeigt haben?Bei den meisten der aufgelisteten Antworten fehlt ein Fall, in dem die Liste doppelte Elemente enthält . In diesem Fall wird dort die Antwort geworfen
IllegalStateException
. Lesen Sie den folgenden Code , um auch Listenduplikate zu behandeln :quelle
quelle
Wenn Sie beispielsweise Objektfelder in Map konvertieren möchten:
Beispielobjekt:
Und Operation Liste in Karte konvertieren:
quelle
Wenn es Ihnen nichts ausmacht, Bibliotheken von Drittanbietern zu verwenden, enthält die Cyclops-React- Bibliothek von AOL (Offenlegung, an der ich beteiligt bin) Erweiterungen für alle JDK-Sammlungstypen , einschließlich Liste und Karte .
quelle
Ich habe versucht, dies zu tun, und festgestellt, dass ich bei Verwendung der obigen Antworten bei der Verwendung
Functions.identity()
des Schlüssels für die Karte Probleme mit der Verwendung einer lokalen Methode hattethis::localMethodName
, die aufgrund von Tippproblemen tatsächlich funktioniert.Functions.identity()
hat in diesem Fall tatsächlich etwas mit der Eingabe zu tun, sodass die Methode nur funktioniert, wennObject
ein Parameter von zurückgegeben und akzeptiert wirdObject
Um dies zu lösen, habe ich stattdessen Schluss gemacht
Functions.identity()
unds->s
stattdessen verwendet.Mein Code, in meinem Fall, um alle Verzeichnisse in einem Verzeichnis aufzulisten und für jedes Verzeichnis den Namen des Verzeichnisses als Schlüssel für die Zuordnung zu verwenden und dann eine Methode mit dem Verzeichnisnamen aufzurufen und eine Sammlung von Elementen zurückzugeben, sieht folgendermaßen aus:
quelle
Sie können mit einem IntStream einen Stream der Indizes erstellen und diese dann in eine Map konvertieren:
quelle
Ich werde schreiben, wie man eine Liste mithilfe von Generika und Umkehrung der Steuerung in eine Karte konvertiert . Nur universelle Methode!
Vielleicht haben wir eine Liste von Ganzzahlen oder eine Liste von Objekten. Die Frage lautet also: Was sollte der Schlüssel der Karte sein?
Schnittstelle erstellen
jetzt mit Umkehrung der Kontrolle:
Wenn wir beispielsweise Buchobjekte haben, soll diese Klasse den Schlüssel für die Karte auswählen
quelle
Ich benutze diese Syntax
quelle
groupingBy
schafft einMap<K,List<V>>
, nicht einMap<K,V>
.String getName();
(nicht Integer)quelle
Dies kann auf zwei Arten erfolgen. Lassen Sie die Person die Klasse sein, mit der wir es demonstrieren werden.
Lassen Sie Personen die Liste der Personen sein, die in die Karte konvertiert werden sollen
1.Verwenden Sie Simple foreach und einen Lambda-Ausdruck in der Liste
2.Verwenden von Collectors on Stream, die in der angegebenen Liste definiert sind.
quelle
Es ist möglich, Streams zu verwenden, um dies zu tun. Um die Notwendigkeit einer expliziten Verwendung zu beseitigen
Collectors
, ist eintoMap
statischer Import möglich (wie von Effective Java, dritte Ausgabe empfohlen).quelle
Hier ist eine Lösung von StreamEx
quelle
Dient sogar diesem Zweck für mich,
quelle
Wenn jeder neue Wert für denselben Schlüsselnamen überschrieben werden muss:
Wenn alle Auswahlmöglichkeiten in einer Liste für einen Namen zusammengefasst werden müssen:
quelle
quelle
Alternativ
guava
kann man kotlin-stdlib verwendenquelle
Schlüssel AA veröffentlichen {12 = ASDFASDFASDF, 7 = EEDDDAD, 4 = CCCC, 3 = BBB, 2 = AA}
quelle