HashMap, чтобы вернуть значение по умолчанию для не найденных ключей? - PullRequest
125 голосов
/ 22 сентября 2011

Возможно ли, чтобы HashMap возвращало значение по умолчанию для всех ключей, которые не найдены в наборе?

Ответы [ 13 ]

150 голосов
/ 31 марта 2014

В Java 8 используйте Map.getOrDefault .Требуется ключ и значение, которое нужно вернуть, если не найдено ни одного соответствующего ключа.

110 голосов
/ 22 сентября 2011

[Обновить]

Как отмечается в других ответах и ​​комментариях, начиная с Java 8 вы можете просто позвонить Map#getOrDefault(...).

[Оригинал]

Нет реализации Map, которая делает это точно, но было бы тривиально реализовать свою собственную, расширив HashMap:

public class DefaultHashMap<K,V> extends HashMap<K,V> {
  protected V defaultValue;
  public DefaultHashMap(V defaultValue) {
    this.defaultValue = defaultValue;
  }
  @Override
  public V get(Object k) {
    return containsKey(k) ? super.get(k) : defaultValue;
  }
}
70 голосов
/ 22 сентября 2011

Используйте Commons ' DefaultsMap , если вы не хотите заново изобретать колесо, например,

Map<String, String> map = new DefaultedMap<>("[NO ENTRY FOUND]");
String surname = map.get("Surname"); 
// surname == "[NO ENTRY FOUND]"

Вы также можете передать существующую карту, если вы не отвечаете за ее создание.

42 голосов
/ 05 июля 2015

Java 8 представила хороший computeIfAbsent метод по умолчанию для интерфейса Map, который хранит вычисленное с ленивым значением значение и поэтому не нарушает контракт карты:

Map<Key, Graph> map = new HashMap<>();
map.computeIfAbsent(aKey, key -> createExpensiveGraph(key));

Происхождение: http://blog.javabien.net/2014/02/20/loadingcache-in-java-8-without-guava/

Юридическая информация: Этот ответ не совпадает точно с тем, который задал OP, но может быть полезен в некоторых случаях, когда заголовок вопроса совпадает, когда число ключей ограничено и кэширование различных значений будет выгодным. Его не следует использовать в противоположном случае с большим количеством ключей и тем же значением по умолчанию, так как это приведет к ненужной трате памяти.

12 голосов
/ 20 августа 2014

Разве вы не можете просто создать статический метод, который делает именно это?

private static <K, V> V getOrDefault(Map<K,V> map, K key, V defaultValue) {
    return map.containsKey(key) ? map.get(key) : defaultValue;
}
10 голосов
/ 31 октября 2012

Вы можете просто создать новый класс, который наследует HashMap, и добавить метод getDefault. Вот пример кода:

public class DefaultHashMap<K,V> extends HashMap<K,V> {
    public V getDefault(K key, V defaultValue) {
        if (containsKey(key)) {
            return get(key);
        }

        return defaultValue;
    }
}

Я думаю, что вам не следует переопределять метод get (K key) в вашей реализации из-за причин, указанных Эдом Стаубом в его комментарии, и потому что вы нарушите контракт интерфейса Map (это потенциально может привести к некоторым трудно обнаруживаемым ошибкам).

5 голосов
/ 05 января 2018

Использование:

myHashMap.getOrDefault(key, defaultValue);
3 голосов
/ 22 сентября 2011

Он делает это по умолчанию.Возвращает null.

1 голос
/ 17 июля 2018

Я нашел LazyMap весьма полезным.

Когда метод get (Object) вызывается с ключом, которого нет на карте, фабрика используется для создания объекта. Созданный объект будет добавлен на карту с использованием запрошенного ключа.

Это позволяет вам сделать что-то вроде этого:

    Map<String, AtomicInteger> map = LazyMap.lazyMap(new HashMap<>(), ()->new AtomicInteger(0));
    map.get(notExistingKey).incrementAndGet();

Вызов get создает значение по умолчанию для данного ключа. Вы указываете, как создать значение по умолчанию с заводским аргументом LazyMap.lazyMap(map, factory). В приведенном выше примере карта инициализируется новым AtomicInteger со значением 0.

0 голосов
/ 31 января 2019

В смешанных проектах Java / Kotlin также учитывайте Map.withDefault Kotlin .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...