Ich möchte Map.computeIfAbsent sehr gerne verwenden, aber es ist zu lange her, dass Lambdas im Undergrad sind.
Fast direkt aus den Dokumenten: Es gibt ein Beispiel für die alte Art, Dinge zu tun:
Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
String key = "snoop";
if (whoLetDogsOut.get(key) == null) {
Boolean isLetOut = tryToLetOut(key);
if (isLetOut != null)
map.putIfAbsent(key, isLetOut);
}
Und der neue Weg:
map.computeIfAbsent(key, k -> new Value(f(k)));
Aber in ihrem Beispiel denke ich, dass ich es nicht ganz "verstehe". Wie würde ich den Code transformieren, um die neue Lambda-Methode zu verwenden, um dies auszudrücken?
java
dictionary
lambda
java-8
Benjamin H.
quelle
quelle
Antworten:
Angenommen, Sie haben den folgenden Code:
Dann sehen Sie die Nachricht
creating a value for "snoop"
genau einmal, da beim zweiten Aufruf voncomputeIfAbsent
bereits ein Wert für diesen Schlüssel vorhanden ist. Derk
Ausdruck im Lambdak -> f(k)
ist nur ein Platzhalter (Parameter) für den Schlüssel, den die Karte zur Berechnung des Werts an Ihr Lambda übergibt. Im Beispiel wird der Schlüssel also an den Funktionsaufruf übergeben.Alternativ könnten Sie schreiben:
whoLetDogsOut.computeIfAbsent("snoop", k -> k.isEmpty());
um das gleiche Ergebnis ohne eine Hilfsmethode zu erzielen (aber die Debugging-Ausgabe wird dann nicht angezeigt). Und noch einfacher, da es sich um eine einfache Delegierung an eine vorhandene Methode handelt, die Sie schreiben könnten: FürwhoLetDogsOut.computeIfAbsent("snoop", String::isEmpty);
diese Delegierung müssen keine Parameter geschrieben werden.Um näher an dem Beispiel in Ihrer Frage zu sein, können Sie es als schreiben
whoLetDogsOut.computeIfAbsent("snoop", key -> tryToLetOut(key));
(es spielt keine Rolle, ob Sie den Parameter benennenk
oderkey
). Oder schreiben Sie es alswhoLetDogsOut.computeIfAbsent("snoop", MyClass::tryToLetOut);
obtryToLetOut
iststatic
oderwhoLetDogsOut.computeIfAbsent("snoop", this::tryToLetOut);
wenntryToLetOut
eine Instanz - Methode.quelle
Kürzlich habe ich auch mit dieser Methode gespielt. Ich habe einen gespeicherten Algorithmus geschrieben, um Fibonacci-Zahlen zu berechnen, der als weiteres Beispiel für die Verwendung der Methode dienen könnte.
Wir können beginnen, indem wir eine Karte definieren und die Werte für die Basisfälle darin einfügen, nämlich
fibonnaci(0)
undfibonacci(1)
:Und für den induktiven Schritt müssen wir lediglich unsere Fibonacci-Funktion wie folgt neu definieren:
Wie Sie sehen können, verwendet die Methode
computeIfAbsent
den bereitgestellten Lambda-Ausdruck, um die Fibonacci-Zahl zu berechnen, wenn die Zahl nicht in der Karte vorhanden ist. Dies stellt eine signifikante Verbesserung gegenüber dem herkömmlichen rekursiven Baumalgorithmus dar.quelle
HashMap
, dass die Interna beschädigt werden, genau wie in bugs.openjdk.java.net/browse/JDK-8172951, und schlägtConcurrentModificationException
in Java 9 fehl ( bugs.openjdk.java.net/browse/JDK-8071667 )Ein anderes Beispiel. Beim Erstellen einer komplexen Karte von Karten ersetzt die Methode computeIfAbsent () die get () -Methode der Karte. Durch Verketten von computeIfAbsent () -Aufrufen werden fehlende Container im laufenden Betrieb durch bereitgestellte Lambda-Ausdrücke erstellt:
quelle
Multi-Map
Dies ist sehr hilfreich, wenn Sie eine Multimap erstellen möchten, ohne auf die Google Guava- Bibliothek zurückgreifen zu müssen
MultiMap
.Angenommen, Sie möchten eine Liste der Schüler speichern, die sich für ein bestimmtes Fach eingeschrieben haben.
Die normale Lösung für die Verwendung der JDK-Bibliothek lautet:
Da es einen Boilerplate-Code gibt, neigen die Leute dazu, Guava zu verwenden
Mutltimap
.Mit Map.computeIfAbsent können wir wie folgt in einer einzelnen Zeile ohne Guave Multimap schreiben.
Stuart Marks & Brian Goetz haben einen guten Vortrag über diese https://www.youtube.com/watch?v=9uTVXxJjuco gehalten
quelle
studentListSubjectWise.stream().collect(Collectors.GroupingBy(subj::getSubjName, Collectors.toList());
Dies erzeugt eine Multi-Map vom TypMap<T,List<T>
in JDK nur präziser imho.