Misalkan kita punya HashMap<String, Integer>
di Jawa.
Bagaimana cara memperbarui (kenaikan) nilai integer dari kunci-string untuk setiap keberadaan string yang saya temukan?
Satu bisa menghapus dan masuk kembali pasangan, tetapi overhead akan menjadi perhatian.
Cara lain adalah dengan hanya menempatkan pasangan baru dan yang lama akan diganti.
Dalam kasus terakhir, apa yang terjadi jika ada tabrakan kode hash dengan kunci baru yang saya coba masukkan? Perilaku yang benar untuk hashtable adalah dengan menetapkan tempat yang berbeda untuk itu, atau membuat daftar dari itu dalam ember saat ini.
getOrDefault
, misalnya:map.put(key, count.getOrDefault(key, 0) + 1);
Java 8 way:
Anda dapat menggunakan
computeIfPresent
metode dan menyediakannya fungsi pemetaan, yang akan dipanggil untuk menghitung nilai baru berdasarkan yang sudah ada.Sebagai contoh,
Alternatifnya, Anda bisa menggunakan
merge
metode, di mana 1 adalah nilai default dan fungsi menambah nilai yang ada dengan 1:Selain itu, ada banyak metode lain yang berguna, seperti
putIfAbsent
,getOrDefault
,forEach
, dllsumber
null
(katakanlahwords.put("hello", null);
), hasilnya masihnull
tidak1
seperti yang saya harapkan.compute()
sebagai gantinya, itu akan menanganinull
nilai juga..merge
adalah solusi sayaInteger::sum
.Metode ini
put
akan mengganti nilai kunci yang ada dan akan membuatnya jika tidak ada.sumber
nullPointer Exception
.null + 1
karena ini akan mencoba membuka kotaknyanull
menjadi bilangan bulat untuk melakukan penambahan.Cara Java 8 yang disederhanakan :
Ini menggunakan metode HashMap yang mengambil nilai untuk kunci, tetapi jika kunci tidak dapat diambil itu mengembalikan nilai default yang ditentukan (dalam hal ini a '0').
Ini didukung dalam Java inti: HashMap <K, V> getOrDefault (Kunci objek, V defaultValue)
sumber
Ganti
Integer
olehAtomicInteger
dan panggil salah satu dariincrementAndGet
/getAndIncrement
metode di atasnya.Alternatifnya adalah dengan membungkus sebuah
int
diMutableInteger
kelas Anda sendiri yang memilikiincrement()
metode, Anda hanya memiliki masalah keamanan benang untuk dipecahkan.sumber
MutableInteger
lebih baik, sepertiAtomicInteger
penggunaanvolatile
, yang memiliki overhead. Saya akan menggunakanint[1]
sebagai gantinyaMutableInteger
.Solusi satu baris:
sumber
Solusi @ Matthew adalah yang paling sederhana dan akan tampil cukup baik dalam banyak kasus.
Jika Anda membutuhkan kinerja tinggi, AtomicInteger adalah solusi yang lebih baik ala @BalusC.
Namun, solusi yang lebih cepat (asalkan keselamatan thread tidak menjadi masalah) adalah menggunakan TObjectIntHashMap yang menyediakan metode kenaikan (kunci) dan menggunakan primitif dan objek yang lebih sedikit daripada membuat AtomicIntegers. misalnya
sumber
Anda dapat menambahkan seperti di bawah ini tetapi Anda perlu memeriksa keberadaannya agar NullPointerException tidak dibuang
sumber
Apakah hash ada (dengan 0 sebagai nilainya) atau apakah "dimasukkan" ke peta pada kenaikan pertama? Jika "diletakkan" pada kenaikan pertama, kode tersebut akan terlihat seperti:
sumber
Mungkin sedikit terlambat tapi ini dua sen saya.
Jika Anda menggunakan Java 8 maka Anda dapat menggunakan metode computeIfPresent . Jika nilai untuk kunci yang ditentukan ada dan bukan nol maka akan mencoba menghitung pemetaan baru yang diberikan kunci dan nilai yang dipetakan saat ini.
Kita juga dapat menggunakan metode lain putIfAbsent untuk meletakkan kunci. Jika kunci yang ditentukan belum dikaitkan dengan nilai (atau dipetakan ke nol) maka metode ini mengaitkannya dengan nilai yang diberikan dan mengembalikan nol, jika tidak mengembalikan nilai saat ini.
Jika peta dibagikan di seluruh utas maka kita dapat menggunakan
ConcurrentHashMap
dan AtomicInteger . Dari dokumen:Kita dapat menggunakannya seperti yang ditunjukkan:
Satu hal yang perlu diperhatikan adalah kita memohon
get
untuk mendapatkan nilai untuk kunciB
dan kemudian memintaincrementAndGet()
nilainya yang tentu sajaAtomicInteger
. Kami dapat mengoptimalkannya karena metodeputIfAbsent
mengembalikan nilai kunci jika sudah ada:Di samping catatan jika kita berencana untuk menggunakan AtomicLong maka sesuai dokumentasi di bawah pertentangan yang tinggi diharapkan throughput LongAdder secara signifikan lebih tinggi, dengan mengorbankan konsumsi ruang yang lebih tinggi. Periksa juga pertanyaan ini .
sumber
Solusi bersih tanpa NullPointerException adalah:
sumber
Karena saya tidak dapat mengomentari beberapa jawaban karena reputasi yang kurang, saya akan memposting solusi yang saya terapkan.
sumber
Gunakan
for
loop untuk menambah indeks:sumber
Ada jawaban yang menyesatkan untuk pertanyaan ini di sini yang menyiratkan metode put Hashtable akan menggantikan nilai yang ada jika kunci ada, ini tidak berlaku untuk Hashtable melainkan untuk HashMap. Lihat Javadoc untuk HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29
sumber
atau
Integer adalah tipe data Primitif http://cs.fit.edu/~ryan/java/language/java-data.html , jadi Anda harus mengeluarkannya, membuat beberapa proses, lalu memasangnya kembali. jika Anda memiliki nilai yang bukan tipe data Primitive, Anda hanya perlu mengeluarkannya, memprosesnya, tidak perlu memasukkannya kembali ke dalam hashmap.
sumber
Mencoba:
CATATAN:
Anda bisa mengubah kunci atau nilai dalam hashmap Anda, tetapi Anda tidak bisa mengubah keduanya sekaligus.
sumber
Gunakan Java8 bawaan dalam fungsi 'computeIfPresent'
Contoh:
sumber