JavaDoc dari ConcurrentHashMap
mengatakan ini:
Suka
Hashtable
tapi tidak sepertiHashMap
, kelas ini tidak memungkinkannull
untuk digunakan sebagai kunci atau nilai.
Pertanyaan saya: Kenapa?
Pertanyaan 2: Mengapa tidak Hashtable
mengizinkan nol?
Saya telah menggunakan banyak HashMaps untuk menyimpan data. Tetapi ketika berganti ke ConcurrentHashMap
saya beberapa kali mengalami masalah karena NullPointerExceptions.
java
concurrenthashmap
Marcel
sumber
sumber
Jawaban:
Dari penulis
ConcurrentHashMap
dirinya sendiri (Doug Lea) :sumber
Optional
nilai s sebagai internalOptional
adalah fitur Java 8, yang saat itu tidak tersedia (Java 5). Anda bisa menggunakanOptional
sekarang, memang.Saya percaya itu adalah, setidaknya sebagian, untuk memungkinkan Anda menggabungkan
containsKey
danget
menjadi satu panggilan. Jika peta dapat menyimpan nol, tidak ada cara untuk mengetahui apakahget
mengembalikan nol karena tidak ada kunci untuk nilai itu, atau hanya karena nilainya nol.Mengapa itu menjadi masalah? Karena tidak ada cara aman untuk melakukannya sendiri. Ambil kode berikut:
Karena
m
ini adalah peta konkuren, kunci k dapat dihapus di antaracontainsKey
danget
panggilan, menyebabkan potongan ini mengembalikan nol yang tidak pernah ada dalam tabel, daripada yang diinginkanKeyNotPresentException
.Biasanya Anda akan menyelesaikannya dengan menyinkronkan, tetapi dengan peta bersamaan yang tentu saja tidak akan berfungsi. Karenanya tanda tangan untuk
get
harus berubah, dan satu-satunya cara untuk melakukan itu dengan cara yang kompatibel-mundur adalah mencegah pengguna memasukkan nilai nol di tempat pertama, dan terus menggunakannya sebagai pengganti untuk "kunci tidak ditemukan".sumber
map.getOrDefault(key, NULL_MARKER)
. Jika itunull
, nilainyanull
. Jika kembaliNULL_MARKER
, nilainya tidak ada.Josh Bloch dirancang
HashMap
; Doug Lea dirancangConcurrentHashMap
. Saya harap itu tidak memfitnah. Sebenarnya saya pikir masalahnya adalah bahwa nulls sering membutuhkan pembungkus sehingga null yang sebenarnya dapat berdiri untuk diinisialisasi. Jika kode klien membutuhkan nol maka dapat membayar biaya pembatalan nol itu sendiri.sumber
Anda tidak dapat menyinkronkan pada nol.
Sunting: Ini tidak persis mengapa dalam hal ini. Saya awalnya berpikir ada sesuatu yang mewah terjadi dengan mengunci hal-hal terhadap pembaruan bersamaan atau menggunakan monitor Obyek untuk mendeteksi jika ada sesuatu yang dimodifikasi, tetapi setelah memeriksa kode sumber tampaknya saya salah - mereka mengunci menggunakan "segmen" berdasarkan pada bitmask hash.
Dalam hal itu, saya curiga mereka melakukannya untuk menyalin Hashtable, dan saya curiga Hashtable melakukannya karena di dunia basis data relasional, null! = Null, jadi menggunakan null sebagai kunci tidak ada artinya.
sumber
ConcurrentHashMap aman digunakan. Saya percaya bahwa tidak mengizinkan kunci dan nilai null adalah bagian dari memastikan bahwa itu adalah thread-safe.
sumber
Saya kira cuplikan dari dokumentasi API berikut ini memberikan petunjuk yang baik: "Kelas ini sepenuhnya dapat dioperasikan dengan Hashtable dalam program yang mengandalkan keamanan utangnya tetapi tidak pada detail sinkronisasi."
Mereka mungkin hanya ingin membuat
ConcurrentHashMap
sepenuhnya kompatibel / dipertukarkan keHashtable
. Dan karenaHashtable
tidak memungkinkan kunci dan nilai null ..sumber
Saya tidak berpikir menolak nilai nol adalah pilihan yang benar. Dalam banyak kasus, kami ingin memasukkan kunci dengan nilai nol ke dalam peta saat ini. Namun, dengan menggunakan ConcurrentHashMap, kami tidak dapat melakukannya. Saya menyarankan agar versi JDK yang akan datang dapat mendukungnya.
sumber