Ich habe mich seit einiger Zeit gefragt, ob es im Rahmen der Best Practice zulässig ist, die containsKey()
Methode nicht zu verwenden java.util.Map
und stattdessen eine Nullprüfung des Ergebnisses von durchzuführen get()
.
Mein Grundprinzip ist, dass es überflüssig erscheint, den Wert zweimal nachzuschlagen - zuerst für containsKey()
und dann wieder für get()
.
Andererseits kann es sein, dass die meisten Standardimplementierungen des Map
Caches die letzte Suche durchführen oder dass der Compiler die Redundanz auf andere Weise beseitigen kann und dass es für die Lesbarkeit des Codes vorzuziehen ist, das containsKey()
Teil beizubehalten .
Ich würde mich sehr über Ihre Kommentare freuen.
quelle
null
, anders behandeln als einen Schlüssel / Wert, der nicht gesetzt ist? Wenn Sie es nicht speziell anders behandeln müssen, können Sie es einfach verwendenget()
Map
istprivate
, kann Ihre Klasse möglicherweise garantieren, dass anull
niemals in die Karte eingefügt wird. In diesem Fall können Sieget()
stattdessen eine Überprüfung auf null anstelle von verwendencontainsKey()
. Dies kann in einigen Fällen klarer und vielleicht etwas effizienter sein.Ich denke, es ist ziemlich normal zu schreiben:
anstatt
Es ist nicht weniger lesbar und etwas effizienter, daher sehe ich keine Gründe, es nicht zu tun. Wenn Ihre Karte null enthalten kann, haben die beiden Optionen natürlich nicht dieselbe Semantik .
quelle
Wie Assylias angedeutet hat, ist dies eine semantische Frage. Im Allgemeinen ist Map.get (x) == null das, was Sie wollen, aber es gibt Fälle, in denen es wichtig ist, includesKey zu verwenden.
Ein solcher Fall ist ein Cache. Ich habe einmal an einem Leistungsproblem in einer Web-App gearbeitet, die ihre Datenbank häufig nach Entitäten abfragte, die es nicht gab. Als ich den Caching-Code für diese Komponente studierte, stellte ich fest, dass die Datenbank abgefragt wurde, wenn cache.get (key) == null. Wenn die Datenbank null zurückgibt (Entität nicht gefunden), würden wir diesen Schlüssel zwischenspeichern -> null Zuordnung.
Der Wechsel zu includesKey löste das Problem, da eine Zuordnung zu einem Nullwert tatsächlich etwas bedeutete. Die Schlüsselzuordnung zu null hatte eine andere semantische Bedeutung als der nicht vorhandene Schlüssel.
quelle
containsKey
gefolgt von aget
ist nur dann redundant, wenn wir apriori wissen, dass Nullwerte niemals zulässig sind. Wenn Nullwerte nicht gültig sind, hat der Aufruf voncontainsKey
eine nicht triviale Leistungseinbuße und ist nur ein Overhead, wie in der folgenden Benchmark gezeigt.Die Java 8-
Optional
Redewendungen -Optional.ofNullable(map.get(key)).ifPresent
oderOptional.ofNullable(map.get(key)).ifPresent
- verursachen einen nicht trivialen Overhead im Vergleich zu nur Vanille-Null-Prüfungen.A
HashMap
verwendet eineO(1)
konstante Tabellensuche, während aTreeMap
eineO(log(n))
Suche verwendet. DascontainsKey
gefolgt von einerget
Redewendung ist viel langsamer, wenn es auf a aufgerufen wirdTreeMap
.Benchmarks
Siehe https://github.com/vkarun/enum-reverse-lookup-table-jmh
TreeMap-Quellreferenz
https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/TreeMap.java
HashMap-Quellreferenz
https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/HashMap.java
quelle
Wir können @assylias Antwort mit Java8 lesbarer machen. Optional,
quelle
In Java, wenn Sie die Implementierung überprüfen
Beide verwenden getNode, um den Abgleich abzurufen, in dem die Hauptarbeit erledigt wird.
Redundanz ist kontextabhängig, wenn Sie beispielsweise ein Wörterbuch in einer Hash-Map gespeichert haben. Wenn Sie die Bedeutung eines Wortes abrufen möchten
tun...
ist redundant.
Wenn Sie jedoch überprüfen möchten, ob ein Wort gültig ist oder nicht, basierend auf dem Wörterbuch. tun...
Über...
ist redundant.
Wenn Sie die HashSet- Implementierung überprüfen , bei der HashMap intern verwendet wird, verwenden Sie ' includesKey ' in der Methode 'enthält'.
quelle