Beim Lesen eines interessanten Artikels behaupten die Jungs, dass der Unterschied zwischen den beiden Funktionen sind:
Beide Funktionen möchten ein Element hinzufügen, wenn der angegebene Schlüssel noch nicht in Map vorhanden ist.
putIfAbsent fügt ein Element mit dem angegebenen Wert hinzu, während computeIfAbsent ein Element mit dem mit dem Schlüssel berechneten Wert hinzufügt. http://www.buggybread.com/2014/10/java-8-difference-between-map.html
Und
Wir haben gesehen, dass putIfAbsent die zwingende Möglichkeit beseitigt, die if-Anweisung definieren zu müssen, aber was ist, wenn das Abrufen der Java-Artikel unsere Leistung wirklich beeinträchtigt?
Um dies zu optimieren, möchten wir die Artikel erst abrufen, wenn wir wirklich sicher sind, dass wir sie benötigen. Dies bedeutet, dass wir vor dem Abrufen der Artikel wissen müssen, ob der Schlüssel fehlt. http://www.deadcoderising.com/2017-02-14-java-8-declarative-ways-of-modifying-a-map-using-compute-merge-and-replace/
Ich habe nicht verstanden, was die Unterschiede sind. Können Sie diese beiden Funktionen näher erläutern?
Antworten:
Unterschied # 1
computeIfAbsent
Nimmt eine Zuordnungsfunktion auf, die aufgerufen wird, um den Wert zu erhalten, wenn der Schlüssel fehlt.putIfAbsent
nimmt den Wert direkt.Wenn der Wert teuer zu erhalten ist, wird dies
putIfAbsent
verschwendet, wenn der Schlüssel bereits vorhanden ist.Ein üblicher "teurer" Wert ist z. B.
new ArrayList<>()
beim Erstellen einerMap<K, List<V>>
, bei der das Erstellen einer neuen Liste, wenn der Schlüssel bereits vorhanden ist (wodurch die neue Liste verworfen wird), unnötigen Müll erzeugt.Unterschied # 2
computeIfAbsent
Gibt "den aktuellen (vorhandenen oder berechneten) Wert zurück, der dem angegebenen Schlüssel zugeordnet ist, oder null, wenn der berechnete Wert null ist".putIfAbsent
Gibt "den vorherigen Wert zurück, der dem angegebenen Schlüssel zugeordnet ist, oder null, wenn für den Schlüssel keine Zuordnung vorhanden war".Wenn der Schlüssel bereits vorhanden ist, geben sie dasselbe zurück. Wenn der Schlüssel jedoch fehlt, wird
computeIfAbsent
der berechnete Wert zurückgegeben, währendputIfAbsent
null zurückgegeben wird.Unterschied # 3
Beide Methoden definieren "nicht vorhanden" als Schlüssel fehlt oder vorhandener Wert ist null, aber:
computeIfAbsent
setzt keinen Nullwert, wenn der Schlüssel fehlt.putIfAbsent
setzt den Wert, wenn der Schlüssel fehlt, auch wenn der Wert null ist.Es macht keinen Unterschied für zukünftige Anrufe an
computeIfAbsent
,putIfAbsent
undget
Anrufe, aber es macht einen Unterschied für Anrufe wiegetOrDefault
undcontainsKey
.quelle
return map.putIfAbsent("key", someMethodReturningNotNullObj);
innerhalb einerfn
Funktion versuchte und mich fragte, warum zum Teufel ich Nullen von meinerfn
Funktion bekam.computeIfAbsent
ist die Art!putIfAbsent
ist nicht konsistent mitput
, daputIfAbsent
ein vorhandener Wert unverändert bleibt, währendput
der Wert ersetzt wird, daher der Teil "falls nicht vorhanden" des Methodennamens.Angenommen, Sie haben eine
Map<String,ValueClass>
.map.putIfAbsent("key", new ValueClass());
wird
ValueClass
trotzdem eine Instanz erstellen , auch wenn der "Schlüssel" -Schlüssel bereits in der istMap
. Dies würde nur eine unnötige Instanz erstellen.Auf der anderen Seite
map.computeIfAbsent("key", k -> new ValueClass());
erstellt nur dann eine
ValueClass
Instanz, wenn sich der Schlüssel "Schlüssel" noch nicht in der befindetMap
(oder einemnull
Wert zugeordnet ist).Ist
computeIfAbsent
daher effizienter.putIfAbsent
ist äquivalent zu:ValueClass value = new ValueClass(); if (map.get("key") == null) { map.put("key",value); }
while
computeIfAbsent
entspricht:if (map.get("key") == null) { map.put("key",new ValueClass()); }
Ein weiterer kleiner Unterschied zwischen den beiden Methoden besteht darin, dass für einen fehlenden Schlüssel
computeIfAbsent
keinnull
Wert angegeben wird.putIfAbsent
werden.quelle
Map<X,List<Y>>
bei der Sie beim ersten Auftreten eines Schlüsselwerts eine Liste erstellen müssen. Ursprünglich hat man get, test, new, put ... Jetzt ist es nur noch dercomputeIfAbsent(..., new ArrayList())
Sie können den Unterschied verstehen, indem Sie sich die Methodensignaturen genau ansehen:
putIfAbsent
Nimmt einen Schlüssel und einen Wert und fügt den Wert in die Karte ein, wenn für diesen Schlüssel kein Wert in der Karte vorhanden ist.computeIfAbsent
nimmt einen Schlüssel und aFunction
. Wenn für diesen Schlüssel in der Karte kein Wert vorhanden ist, wird die Funktion aufgerufen, um den Wert zu erstellen, der dann in die Karte eingefügt wird.Wenn Sie den Wert bereits haben, verwenden Sie
putIfAbsent
.Wenn Sie den Wert noch nicht haben und das Erstellen des Werts eine teure Operation ist (z. B. muss der Wert in einer Datenbank nachgeschlagen werden), verwenden Sie ihn
computeIfAbsent
, damit die teure Operation für den Fall nicht ausgeführt werden muss Die Karte enthält bereits einen Wert für den angegebenen Schlüssel.quelle
Vielleicht können die Standardimplementierungen ein bisschen mehr klarstellen ...
default V putIfAbsent(K key, V value)
Die Standardimplementierung entspricht für diese Karte:V v = map.get(key); if (v == null) v = map.put(key, value); return v;
Auf der anderen Seite:
default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
ist äquivalent zu:
if (map.get(key) == null) { V newValue = mappingFunction.apply(key); if (newValue != null) map.put(key, newValue); }
quelle
V putIfAbsent(K key, V value)
- Wenn der angegebene Schlüssel noch keinem Wert zugeordnet ist (oder null zugeordnet ist), wird versucht, seinen Wert mithilfe der angegebenen Zuordnungsfunktion zu berechnen und in diese Zuordnung einzugeben, sofern nicht null.V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
- Wenn der angegebene Schlüssel noch keinem Wert zugeordnet ist (oder null zugeordnet ist), wird versucht, seinen Wert mithilfe der angegebenen Zuordnungsfunktion zu berechnen und in diese Zuordnung einzugeben, sofern nicht null.Das Lesen der Dokumentation kann Ihnen eine offensichtlichere Antwort geben. https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
quelle
Nehmen Sie dieses einfache Beispiel für
putIfAbsent()
:Map myMap = new HashMap(); myMap.put(1,"ABC"); myMap.put(2,"XYZ"); myMap.put(3,"GHI"); //Output of map till this point is : 1-> "ABC", 2-> "XYZ", 3-> "GHI" myMap.putIfAbsent(3,"cx"); //Output of map till this point is : 1-> "ABC", 2-> "XYZ", 3-> "GHI"
cx
wird der Wert von sein,3
wenn3
in der Karte noch kein Wert von vorhanden ist .quelle
putIfAbsent()
undcomputeIfAbsent
nicht nur nach dem, wasputIfAbsent()
tut.key
undvalue
hier. SieheClass HashMap<K,V>
.Diese Frage wurde bereits beantwortet. Ich habe ein wenig Zeit gebraucht, um zu verstehen ("Eine teure Operation muss nicht durchgeführt werden, falls die Karte bereits einen Wert für den angegebenen Schlüssel in computeIfAbsent enthält"). Hoffe, dass dies für andere hilfreich sein wird:
putIfAbsent()
verhält sich einfach so,put()
als ob map bereits den Wert für den angegebenen Schlüssel enthält.putIfAbsent()
prüft nur, ob der Schlüssel null ist oder nicht. Wenn es nicht null ist, gibt es den Wert zurück und ruft diesen Wert erneut ab.Es
computeIfAbsent()
gibt jedoch eine Nullprüfung für Schlüssel und Wert. Wenn es bei der Nullprüfung auf Wert nicht null ist, wird der vorhandene Wert aus dem Kartenobjekt newValue zugewiesen und zurückgegeben. Aus diesem Grund muss der Wert nicht erneut abgerufen werden, da der vorhandene Wert aus der Karte wiederverwendet wird.Siehe folgendes Programm als Referenz:
public class MapTest1 { public static final String AJAY_DEVGAN = "Ajay Devgn"; public static final String AUTOBIOGRAPHY = "Autobiography"; public static void main(String[] args) { MapTest1 mt = new MapTest1(); mt.testPutCompute(); } private void testPutCompute() { Map<String, List<String>> movies = getMovieObject(); System.out.println("\nCalling putIfAbsent method....."); //System.out.println(movies.get(AJAY_DEVGAN)); //movies.put(AJAY_DEVGAN, getAjayDevgnMovies()); movies.putIfAbsent(AJAY_DEVGAN, getAjayDevgnMovies()); System.out.println("\nCalling computeIfAbsent method......"); //System.out.println(movies.get(AUTOBIOGRAPHY)); movies.computeIfAbsent(AUTOBIOGRAPHY, t -> getAutobiographyMovies()); } private Map<String, List<String>> getMovieObject() { Map<String, List<String>> movies = new HashMap<>(); movies.put(AJAY_DEVGAN, getAjayDevgnMovies()); movies.put(AUTOBIOGRAPHY, getAutobiographyMovies()); System.out.println(movies); return movies; } private List<String> getAutobiographyMovies() { System.out.println("Getting autobiography movies"); List<String> list = new ArrayList<>(); list.add("M.S. Dhoni - The Untold Story"); list.add("Sachin: A Billion Dreams"); return list; } private List<String> getAjayDevgnMovies() { System.out.println("Getting Ajay Devgn Movies"); List<String> ajayDevgnMovies = new ArrayList<>(); ajayDevgnMovies.add("Jigar"); ajayDevgnMovies.add("Pyar To Hona Hi Tha"); return ajayDevgnMovies; } }
Siehe folgenden Code für
putIfAbsent()
undcomputeIfAbsent()
von der SchnittstelleMap.class
public interface Map<K,V> { ..... default V putIfAbsent(K key, V value) { V v = get(key); if (v == null) { v = put(key, value); } return v; } default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { Objects.requireNonNull(mappingFunction); V v; if ((v = get(key)) == null) { V newValue; if ((newValue = mappingFunction.apply(key)) != null) { put(key, newValue); return newValue; } } return v; } ......... }
quelle