[英]How can I avoid repeating code initializing a hashmap of hashmap?
每個客戶都有一個 id 和許多帶有日期的發票,這些發票按 id 存儲為客戶的 Hashmap,按日期存儲為發票的哈希圖:
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);
}
Java 解決方案似乎是使用getOrDefault
:
HashMap<LocalDateTime, Invoice> allInvoices = allInvoicesAllClients.getOrDefault(
id,
new HashMap<LocalDateTime, Invoice> (){{ put(date, invoice); }}
);
但是如果 get 不為空,我仍然希望 put (date, invoice) 執行,並且仍然需要向“allInvoicesAllClients”添加數據。 所以它似乎沒有多大幫助。
這是Map#computeIfAbsent
一個很好的用例。 您的代碼段本質上等同於:
allInvoicesAllClients.computeIfAbsent(id, key -> new HashMap<>()).put(date, invoice);
如果id
沒有作為allInvoicesAllClients
的鍵allInvoicesAllClients
,那么它將創建從id
到新HashMap
映射並返回新的HashMap
。 如果id
作為鍵存在,那么它將返回現有的HashMap
。
對於這種特殊情況, computeIfAbsent
是一個很好的解決方案。 總的來說,我想注意以下幾點,因為還沒有人提到它:
“外部”哈希映射僅存儲對“內部”哈希映射的引用,因此您可以重新排序操作以避免代碼重復:
HashMap<LocalDateTime, Invoice> allInvoices = allInvoicesAllClients.get(id);
if (allInvoices == null) {
allInvoices = new HashMap<>();
allInvoicesAllClients.put(id, allInvoices);
}
allInvoices.put(date, invoice); // <--- no longer repeated
您幾乎不應該使用“雙括號”映射初始化。
{{ put(date, invoice); }}
在這種情況下,您應該使用computeIfAbsent
allInvoicesAllClients.computeIfAbsent(id, (k) -> new HashMap<>())
.put(date, allInvoices);
如果此 ID 沒有映射,您將插入一個。 結果將是現有的或計算出的地圖。 然后,您可以put
項目放入該地圖中,並保證它不會為空。
這比其他答案更長,但恕我直言更具可讀性:
if(!allInvoicesAllClients.containsKey(id))
allInvoicesAllClients.put(id, new HashMap<LocalDateTime, Invoice>());
allInvoicesAllClients.get(id).put(date, invoice);
您在這里做兩件單獨的事情:確保HashMap
存在,並向其中添加新條目。
現有代碼確保在注冊哈希映射之前先插入新元素,但這不是必需的,因為HashMap
不關心這里的排序。 這兩個變體都不是線程安全的,因此您不會丟失任何東西。
因此,就像@Heinzi 建議的那樣,您可以將這兩個步驟分開。
我還會做的是將HashMap
的創建卸載到allInvoicesAllClients
對象,因此get
方法不能返回null
。
這也減少了單獨線程之間競爭的可能性,這些線程既可以從get
獲取null
指針,然后又決定put
一個新的HashMap
put
單個條目——第二個put
可能會丟棄第一個,從而丟失Invoice
對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.