Использует java Map.containsKey() избыточно при использовании map.get()
Мне было интересно некоторое время, допустимо ли в рамках лучшей практики воздержаться от использования метода containsKey()
на java.util.Map
и вместо этого выполнить нулевую проверку результата из get()
.
Мое объяснение состоит в том, что кажется излишним выполнять поиск значения дважды - сначала для containsKey()
, а затем снова для get()
.
С другой стороны, может быть, что большинство стандартных реализаций Map
кэшируют последний поиск или что компилятор может в противном случае избавиться от избыточности, и что для удобочитаемости кода предпочтительнее поддерживать containsKey()
часть.
Я был бы очень признателен за ваши комментарии.
Ответы
Ответ 1
Некоторым реализациям карты разрешено иметь нулевые значения, например HashMap, в этом случае, если get(key)
возвращает null
, это не гарантирует, что на карте, связанной с этим ключом, нет записи.
Итак, если вы хотите узнать, содержит ли карта ключ, используйте Map.containsKey
. Если вам просто нужно значение, сопоставленное с ключом, используйте Map.get(key)
. Map.containsKey
будет бесполезным и повлияет на производительность. Более того, в случае одновременного доступа к карте (например, ConcurrentHashMap
) после тестирования Map.containsKey(key)
есть вероятность, что запись будет удалена другим потоком, прежде чем вы вызовете Map.get(key)
.
Ответ 2
Я думаю, что довольно стандартно писать:
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
}
Это не менее читаемо и немного более эффективно, поэтому я не вижу причин не делать этого. Очевидно, что , если ваша карта может содержать нуль, эти два параметра не имеют одинаковой семантики.
Ответ 3
Как указывалось assylias, это семантический вопрос. Как правило, Map.get(x) == null - это то, что вы хотите, но бывают случаи, когда важно использовать containsKey.
Одним из таких случаев является кеш. Однажды я работал над проблемой производительности в веб-приложении, которое запрашивало его базу данных, часто ищущую сущности, которых не было. Когда я изучил код кеширования для этого компонента, я понял, что он запрашивает базу данных, если cache.get(key) == null. Если база данных вернула null (сущность не найдена), мы будем кэшировать этот ключ → null mapping.
Переключение на containsKey решило проблему, потому что сопоставление с нулевым значением фактически означало что-то. Ключевое сопоставление с нулевым значением имело другое смысловое значение, чем ключ, не существующий.
Ответ 4
Мы можем сделать ответ @assylias более читаемым с помощью Java8 Необязательно,
Optional.ofNullable(map.get(key)).ifPresent(value -> {
//do something with value
};)