Setiap klien memiliki id, dan banyak faktur, dengan tanggal, disimpan sebagai Hashmap klien dengan id, dari hashmap faktur berdasarkan tanggal:
HashMap<LocalDateTime, Invoice> allInvoices = allInvoicesAllClients.get(id);
if(allInvoices!=null){
allInvoices.put(date, invoice); //<---REPEATED CODE
}else{
allInvoices = new HashMap<>();
allInvoices.put(date, invoice); //<---REPEATED CODE
allInvoicesAllClients.put(id, allInvoices);
}
Solusi Java tampaknya menggunakan getOrDefault
:
HashMap<LocalDateTime, Invoice> allInvoices = allInvoicesAllClients.getOrDefault(
id,
new HashMap<LocalDateTime, Invoice> (){{ put(date, invoice); }}
);
Tetapi jika get bukan null, saya masih ingin mengeksekusi (tanggal, faktur), dan juga menambahkan data ke "allInvoicesAllClients" masih diperlukan. Jadi sepertinya tidak banyak membantu.
Jawaban:
Ini adalah kasus penggunaan yang sangat baik untuk
Map#computeIfAbsent
. Cuplikan Anda pada dasarnya setara dengan:Jika
id
tidak hadir sebagai kunciallInvoicesAllClients
, maka itu akan membuat pemetaan dariid
ke yang baruHashMap
dan mengembalikan yang baruHashMap
. Jikaid
ada sebagai kunci, maka itu akan mengembalikan yang sudah adaHashMap
.sumber
allInvoicesAllClients.computeIfAbsent(id, key -> Map.of(date, invoice))
Map.of
menciptakan yang tidak dapat dimodifikasiMap
, yang saya tidak yakin ingin OP.computeIfAbsent
adalah solusi tepat untuk kasus khusus ini. Secara umum, saya ingin mencatat yang berikut, karena belum ada yang menyebutkannya:Hashmap "outer" hanya menyimpan referensi ke hashmap "inner", jadi Anda bisa menyusun ulang operasi untuk menghindari duplikasi kode:
sumber
computeIfAbsent()
metode mewahnya !Anda seharusnya tidak pernah menggunakan inisialisasi peta "penjepit ganda".
Dalam hal ini, Anda harus menggunakan
computeIfAbsent
Jika tidak ada peta untuk ID ini, Anda akan memasukkan satu. Hasilnya adalah peta yang ada atau yang dihitung. Anda kemudian dapat
put
item di peta itu dengan jaminan bahwa itu tidak akan nol.sumber
id
dilakukan juga. Anda dapat menganggapcomputeIfAbsent
sebagai putusan bersyarat jika Anda suka. Dan itu mengembalikan nilainya juga{{ }}
memiliki makna khusus, yang tidak.Ini lebih panjang dari jawaban yang lain, tetapi jauh lebih mudah dibaca:
sumber
Anda sedang melakukan dua hal terpisah di sini: memastikan bahwa
HashMap
ada, dan menambahkan entri baru ke sana.Kode yang ada memastikan untuk memasukkan elemen baru terlebih dahulu sebelum mendaftarkan peta hash, tetapi itu tidak perlu, karena
HashMap
tidak peduli tentang pemesanan di sini. Varian tidak ada threadsafe, sehingga Anda tidak kehilangan apa pun.Jadi, seperti yang disarankan @Heinzi, Anda bisa membagi dua langkah ini.
Apa yang saya juga akan lakukan adalah offload penciptaan
HashMap
keallInvoicesAllClients
objek, sehinggaget
metode tidak dapat kembalinull
.Ini juga mengurangi kemungkinan balapan antara utas-utas terpisah yang keduanya bisa mendapatkan
null
pointer dariget
dan kemudian memutuskan untukput
yang baruHashMap
dengan satu entri - yang keduaput
mungkin akan membuang yang pertama, kehilanganInvoice
objek.sumber