Использует java Map.containsKey () избыточен при использовании map.получить()
мне было интересно в течение некоторого времени, допустимо ли в рамках лучшей практики воздерживаться от использования containsKey()
метод on java.util.Map
и вместо этого сделайте нулевую проверку результата от get()
.
мое обоснование заключается в том, что кажется избыточным выполнять поиск значения дважды - сначала для containsKey()
и затем на get()
.
С другой стороны, может быть, что большинство стандартных реализаций Map
кэшировать последний поиск или что компилятор может в противном случае избавьтесь от избыточности, и что для удобочитаемости кода предпочтительнее поддерживать containsKey()
часть.
Я был бы очень признателен за ваши комментарии.
5 ответов
некоторые реализации карты могут иметь нулевые значения, например HashMap, в этом случае, если get(key)
возвращает null
это не гарантирует, что нет записи в карте, связанной с этим ключом.
Итак, если вы хотите знать, содержит ли карта ключ use Map.containsKey
. Если вам просто нужно значение, сопоставленное с ключом, используйте Map.get(key)
. Если эта карта допускает значения NULL, то возвращаемое значение null не обязательно означает, что карта не содержит отображения для ключа; в таком случае Map.containsKey
бесполезно и повлияет на производительность. Более того, в случае параллельного доступа к карте (например,ConcurrentHashMap
), после того, как вы протестировали Map.containsKey(key)
существует вероятность того, что запись будет удалена другим потоком перед вызовом Map.get(key)
.
Я думаю, что это довольно стандартно писать:
Object value = map.get(key);
if (value != null) {
//do something with value
}
вместо
if (map.containsKey(key)) {
Object value = map.get(key);
//do something with value
}
это не менее читабельно и немного более эффективно, поэтому я не вижу причин не делать этого. Очевидно если ваша карта может содержать null, эти два параметра не имеют одинаковой семантики.
Как указал ассилий, это семантический вопрос. В Общем, Карта.get (x) == null-это то, что вы хотите, но есть случаи, когда важно использовать containsKey.
одним из таких случаев является кэш. Однажды я работал над проблемой производительности в веб-приложении, которое часто запрашивало свою базу данных в поисках несуществующих сущностей. Когда я изучил код кэширования для этого компонента, я понял, что он запрашивает базу данных, если кэш.get (key) == null. Если база данных возвращена null (сущность не найдена), мы будем кэшировать этот ключ -> null mapping.
переключение на containsKey решило проблему, потому что сопоставление с нулевым значением на самом деле что-то значило. Сопоставление ключа с null имело другое семантическое значение, чем несуществующий ключ.
мы можем сделать ответ @assylias более читаемым с Java8 необязательным,
Optional.ofNullable(map.get(key)).ifPresent(value -> {
//do something with value
};)
в Java, если вы проверяете реализации
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
оба используют getNode для получения соответствия, где выполняется основная работа.
избыточность является контекстной, например, если у вас есть словарь, хранящийся в хэш-карте. Когда вы хотите получить значение слова
делаешь...
if(dictionary.containsKey(word)) {
return dictionary.get(word);
}
избыточна.
но если вы хотите, чтобы проверить слово действительно или не на основе словаря. делающий...
return dictionary.get(word) != null;
более...
return dictionary.containsKey(word);
избыточна.
если вы проверяете поиска HashSet реализация, которая использует HashMap внутренне, используйте "containsKey" в методе "contains".
public boolean contains(Object o) {
return map.containsKey(o);
}