Saya telah bertanya-tanya selama beberapa waktu apakah diperbolehkan dalam praktik terbaik untuk menahan diri dari menggunakan containsKey()
metode ini java.util.Map
dan sebaliknya melakukan pemeriksaan nol pada hasil dari get()
.
Alasan saya adalah bahwa tampaknya mubazir untuk melakukan pencarian nilai dua kali - pertama untuk yang containsKey()
dan kemudian untuk get()
.
Di sisi lain, mungkin sebagian besar implementasi standar Map
cache pencarian terakhir atau yang sebaliknya dapat dilakukan oleh compiler dengan redundansi, dan agar kode dapat dibaca, lebih disukai untuk mempertahankan containsKey()
bagian tersebut.
Saya sangat menghargai komentar Anda.
sumber
null
, apakah Anda ingin memperlakukannya secara berbeda dengan kunci / nilai yang tidak disetel? Jika Anda tidak secara khusus perlu memperlakukannya secara berbeda, Anda dapat menggunakanget()
Map
adalahprivate
, kelas Anda mungkin bisa menjaminnull
tidak pernah dimasukkan ke dalam peta. Dalam hal ini, Anda dapat menggunakanget()
diikuti dengan pemeriksaan null, bukancontainsKey()
. Melakukannya bisa lebih jelas, dan mungkin sedikit lebih efisien, dalam beberapa kasus.Menurut saya cukup standar untuk menulis:
Object value = map.get(key); if (value != null) { //do something with value }
dari pada
if (map.containsKey(key)) { Object value = map.get(key); //do something with value }
Ini tidak kurang mudah dibaca dan sedikit lebih efisien jadi saya tidak melihat alasan untuk tidak melakukannya. Jelas jika peta Anda dapat berisi null, kedua opsi tersebut tidak memiliki semantik yang sama .
sumber
Seperti yang ditunjukkan oleh assylias, ini adalah pertanyaan semantik. Umumnya, Map.get (x) == null adalah yang Anda inginkan, tetapi ada kasus di mana penting untuk menggunakan containsKey.
Salah satu kasus tersebut adalah cache. Saya pernah menangani masalah kinerja di aplikasi web yang sering menanyakan database-nya mencari entitas yang tidak ada. Ketika saya mempelajari kode caching untuk komponen itu, saya menyadari itu menanyakan database jika cache.get (key) == null. Jika database mengembalikan null (entitas tidak ditemukan), kami akan menyimpan kunci itu ke cache -> pemetaan null.
Beralih ke containsKey memecahkan masalah karena pemetaan ke nilai null sebenarnya berarti sesuatu. Pemetaan kunci ke nol memiliki arti semantik yang berbeda dengan kunci yang tidak ada.
sumber
containsKey
diikuti oleh sebuahget
redundan hanya jika kita tahu apriori bahwa nilai null tidak akan pernah diizinkan. Jika nilai null tidak valid, pemanggilancontainsKey
memiliki penalti performa non-sepele dan hanya overhead seperti yang ditunjukkan pada tolok ukur di bawah ini.Optional
Idiom Java 8 -Optional.ofNullable(map.get(key)).ifPresent
atauOptional.ofNullable(map.get(key)).ifPresent
- menimbulkan overhead yang tidak sepele dibandingkan dengan pemeriksaan nol vanilla saja.A
HashMap
menggunakanO(1)
pencarian tabel konstan sedangkan aTreeMap
menggunakanO(log(n))
pencarian. ThecontainsKey
diikuti denganget
idiom jauh lebih lambat ketika dijalankan padaTreeMap
.Tolak ukur
Lihat https://github.com/vkarun/enum-reverse-lookup-table-jmh
// t1 static Type lookupTreeMapNotContainsKeyThrowGet(int t) { if (!lookupT.containsKey(t)) throw new IllegalStateException("Unknown Multihash type: " + t); return lookupT.get(t); } // t2 static Type lookupTreeMapGetThrowIfNull(int t) { Type type = lookupT.get(t); if (type == null) throw new IllegalStateException("Unknown Multihash type: " + t); return type; } // t3 static Type lookupTreeMapGetOptionalOrElseThrow(int t) { return Optional.ofNullable(lookupT.get(t)).orElseThrow(() -> new IllegalStateException("Unknown Multihash type: " + t)); } // h1 static Type lookupHashMapNotContainsKeyThrowGet(int t) { if (!lookupH.containsKey(t)) throw new IllegalStateException("Unknown Multihash type: " + t); return lookupH.get(t); } // h2 static Type lookupHashMapGetThrowIfNull(int t) { Type type = lookupH.get(t); if (type == null) throw new IllegalStateException("Unknown Multihash type: " + t); return type; } // h3 static Type lookupHashMapGetOptionalOrElseThrow(int t) { return Optional.ofNullable(lookupH.get(t)).orElseThrow(() -> new IllegalStateException("Unknown Multihash type: " + t)); }
Referensi sumber TreeMap
https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/TreeMap.java
Referensi sumber HashMap
https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/HashMap.java
sumber
Kami dapat membuat jawaban @assylias lebih mudah dibaca dengan Java8 Opsional,
Optional.ofNullable(map.get(key)).ifPresent(value -> { //do something with value };)
sumber
Di Java jika Anda memeriksa implementasinya
public boolean containsKey(Object key) { return getNode(hash(key), key) != null; } public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; }
keduanya menggunakan getNode untuk mengambil pencocokan, tempat pekerjaan utama diselesaikan.
redundansi bersifat kontekstual, misalnya jika Anda memiliki kamus yang disimpan dalam peta hash. Ketika Anda ingin mendapatkan kembali arti sebuah kata
perbuatan...
if(dictionary.containsKey(word)) { return dictionary.get(word); }
berlebihan.
tetapi jika Anda ingin memeriksa kata itu valid atau tidak berdasarkan kamus. perbuatan...
return dictionary.get(word) != null;
lebih...
return dictionary.containsKey(word);
berlebihan.
Jika Anda memeriksa implementasi HashSet , yang menggunakan HashMap secara internal, gunakan metode 'containsKey' dalam 'berisi'.
public boolean contains(Object o) { return map.containsKey(o); }
sumber