У каждого клиента есть идентификатор и множество счетов с датами, которые хранятся в виде 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 не равен null, я по-прежнему хочу, чтобы put (дата, счет-фактура) выполнялся, а добавление данных в «allInvoicesAllClients» все еще необходимо. Так что, похоже, это не сильно помогает.
Ответы:
Это отличный вариант использования для
Map#computeIfAbsent
. Ваш фрагмент по сути эквивалентен:Если
id
его нет в качестве ключаallInvoicesAllClients
, он создаст отображение изid
новогоHashMap
и вернет новоеHashMap
. Еслиid
присутствует в качестве ключа, то он вернет существующийHashMap
.источник
allInvoicesAllClients.computeIfAbsent(id, key -> Map.of(date, invoice))
Map.of
создает неизменяемоеMap
, которое я не уверен, что ОП хочет.computeIfAbsent
это отличное решение для этого конкретного случая. В общем, хотелось бы отметить следующее, так как никто еще не упомянул об этом:«Внешний» hashmap просто хранит ссылку на «внутренний» hashmap, так что вы можете просто изменить порядок операций, чтобы избежать дублирования кода:
источник
computeIfAbsent()
методом!Вы почти никогда не должны использовать инициализацию карты "двойной скобкой".
В этом случае вы должны использовать
computeIfAbsent
Если для этого идентификатора карты нет, вы ее вставите. Результатом будет существующая или вычисленная карта. Затем вы можете
put
размещать элементы на этой карте, гарантируя, что она не будет нулевой.источник
id
сделано, а также. Вы можете думать обcomputeIfAbsent
условном путе, если хотите. И это также возвращает значение{{ }}
имеет особое значение, чего не происходит.Это длиннее, чем другие ответы, но имхо гораздо более читабельно:
источник
Здесь вы делаете две разные вещи: гарантируете
HashMap
существование и добавляете в него новую запись.Существующий код обязательно вставляет новый элемент перед регистрацией хеш-карты, но в этом нет необходимости, потому что здесь нет необходимости
HashMap
в упорядочении. Ни один из вариантов не является потокобезопасным, поэтому вы ничего не теряете.Итак, как предложил @Heinzi, вы можете просто разделить эти два шага.
Я также хотел бы разгрузить создание объекта
HashMap
доallInvoicesAllClients
объекта, чтобыget
метод не мог вернутьсяnull
.Это также уменьшает возможность гонок между отдельными потоками, которые могут как получить
null
указатели, такget
и затем принять решениеput
о новомHashMap
с одной записью - второйput
, вероятно, отбросит первый, потерявInvoice
объект.источник