如何避免重复代码初始化哈希映射的哈希映射?

2022-09-01 15:03:34

每个客户都有一个ID,以及许多带有日期的发票,按id存储为客户的哈希图,按日期存储为发票的哈希图:

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 不为 null,我仍然希望执行 put(日期、发票),并且仍然需要向“allInvoicesAllClients”添加数据。因此,它似乎没有多大帮助。


答案 1

这是Map#computeIfAbsent的一个很好的用例。您的代码段实质上等效于:

allInvoicesAllClients.computeIfAbsent(id, key -> new HashMap<>()).put(date, invoice);

如果 中未作为键存在,则它将创建从 到新的映射并返回新的 .如果 作为键存在,则它将返回现有的 .idallInvoicesAllClientsidHashMapHashMapidHashMap


答案 2

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