map.getOrDefault().add() в Java не работает

#java #hashmap

#java #hashmap

Вопрос:

Традиционный код работает хорошо, как показано ниже:

 Map<Integer, List<Integer>> map = new HashMap<>();
if (!map.containsKey(1)) {
   map.put(1, new ArrayList<>());
}
map.get(1).add(2);
  

Теперь я хотел бы попробовать магию getOrDefault:

 map.getOrDefault(1, new ArrayList<>()).add(2);
  

Но если я использую приведенную выше строку, то map.get(1) значение равно нулю.

Почему?

Комментарии:

1. Где он выводит значение null?

2. map.getOrDefault(1, новый список массивов<>()).add(2); выведет значение null

3. List.add возвращает a boolean . О каком нулевом значении мы говорим? Вы получаете исключение NullPointerException .add(2) (что было бы невероятно)?

Ответ №1:

Потому getOrDefault что, как следует из его названия, получает только данные с карты. Он не добавляет новый KVP на карту. Когда ключ отсутствует, значение по умолчанию, которое вы передаете getOrDefault , возвращается, но не добавляется к карте, поэтому вы добавляете 2 в список массивов, который немедленно выбрасывается.

Другими словами, это то, что делает ваш getOrDefault код:

 ArrayList<Integer> value;
if (!map.containsKey(1)) {
    value = new ArrayList<>();
} else {
    value = map.get(1);
}
value.add(2);
  

Вы должны использовать computeIfAbsent вместо этого. Этот метод фактически добавляет возвращаемое значение из функции в карту, если ключ отсутствует:

 map.computeIfAbsent(1, x -> new ArrayList<>()).add(2);
  

Комментарии:

1. imo очень плохая реализация хорошей идеи: computeIfAbsent делает то, что хочет автор, но мы ничего не вычисляем, когда добавляем новый ArrayList , поэтому метод делает вещи, не связанные с тем, как он вызывается, и это создает запутанный код. Вместо этого я предпочитаю использовать традиционную версию, потому что она делает именно то, что, похоже, должно делать.

Ответ №2:

или вы могли бы сделать:

 if(!map.contansKey(1)) map.put(1, new ArrayList<>());
map.get(1).add(2);
  

так что вы можете сохранить эти строки 😉