Почему полезно иметь нулевые значения или нулевые ключи в хэш-картах?
Hashtable
не разрешает нулевые ключи или значения, а HashMap
допускает нулевые значения и 1 нулевой ключ.
Вопросы:
- Почему это так?
- Как полезно иметь такой ключ и значения в HashMap?
Ответы
Ответ 1
1. Почему это так?
HashMap является более новым, чем Hashtable, и исправляет некоторые из его ограничений.
Я могу только догадываться, о чем думали дизайнеры, но вот мои догадки:
- Hashtable вычисляет хэш для каждого ключа, вызывая
hashCode
для каждого ключа. Это не сработает, если ключ был пустым, поэтому это может быть причиной отказа от нулей в качестве ключей.
- Метод
Hashtable.get
возвращает null, если ключ отсутствует. Если значение null было допустимым, было бы двусмысленно относиться к тому, что значение null означает, что ключ присутствовал, но имел значение null или если ключ отсутствовал. Неоднозначность - это плохо, поэтому это может быть причиной отказа от нулей в качестве значений.
Однако оказывается, что иногда вы действительно хотите сохранить нули, чтобы ограничения были удалены в HashMap. Следующее предупреждение было также включено в документацию для HashMap.get
:
Возвращаемое значение null необязательно указывает, что карта не содержит отображения для ключа; также возможно, что карта явно отображает ключ в значение null.
2. Как полезно иметь такой ключ и значения в HashMap?
Полезно явно хранить нуль, чтобы различать ключ, который, как вы знаете, существует, но не имеет связанного значения и ключа, которого не существует. Примером может служить список зарегистрированных пользователей и их дней рождения. Если вы просите указать определенный день рождения пользователя, вы хотите, чтобы он отличал этого пользователя от существующего и существующего пользователя, но не вступил в свой день рождения.
Я не могу придумать какую-либо (хорошую) причину для того, чтобы хранить нуль в качестве ключа, и вообще я бы посоветовал не использовать null в качестве ключа, но, по-видимому, есть хотя бы один человек, где нужны эти ключи который может быть нулевым.
Ответ 2
Ну, я думаю, что Марк Байерс прекрасно ответил, поэтому просто пример, где нулевые значения и ключи могут быть полезны:
Представьте, что у вас есть дорогостоящая функция, которая всегда возвращает тот же результат для одного и того же ввода. Карта - это простой способ кэширования своих результатов. Может быть, иногда функция возвращает null, но вам все равно нужно ее сохранить, потому что исполнение дорого. Таким образом, нулевые значения должны быть сохранены. То же самое относится к нулевому ключу, если это принятый ввод для функции.
Ответ 3
HashTable - очень старый класс из JDK 1.0. Классы, которые находятся на месте от JDK 1.0, называются Legacy, и по умолчанию они синхронизированы.
Чтобы понять это, в первую очередь вам нужно понять комментарии, написанные автором в этом классе.
"Этот класс реализует хэш-таблицу, которая отображает ключи к значениям. Любой ненулевой объект может использоваться как ключ или как значение. Чтобы успешно хранить и извлекать объекты из хеш-таблицы, объекты, используемые в качестве ключей, должны реализовывать метод hashCode и метод равен."
Класс HashTable реализован в хэш-механизме, означает сохранение любой пары ключ-значение, требуемый хэш-код ключевого объекта. HashTable вычисляет хэш для каждого ключа, вызывая hashCode на каждом ключе. Это не сработает. Если ключ будет равен нулю, он не сможет выдавать хэш, он будет бросать NullPointerException и аналогичный случай для значения, он бросает null, если значение равно null.
Но позже было осознано, что нулевой ключ и значение имеют свое значение, поэтому в последующих реализованных классах, таких как класс HashMap, допускается один нулевой ключ и несколько нулевых значений.
Для HashMap он допускает нулевые ключи, и для ключей есть нулевая проверка, если ключ равен нулю, тогда этот элемент будет храниться в нулевом местоположении в массиве Entry.
Мы не можем иметь более одного ключа Null в HashMap, потому что Keys уникальны, поэтому допускается только один ключ Null и многие значения Null.
USE - нулевой ключ, который мы можем использовать для некоторого значения по умолчанию.
Модифицированная и лучшая реализация HashTable позднее была представлена как ConcurrentHashMap.
Ответ 4
В дополнение к тому, что ответил Марк Байерс,
Null рассматривается как данные, и его необходимо сохранить в качестве значения для дальнейшей проверки. Во многих случаях значение null как значение может использоваться для проверки наличия ключа, но ему не присваивается никакого значения, поэтому некоторые действия могут быть приняты соответствующим образом. Это можно сделать, предварительно проверив, существует ли ключ, а затем получает значение.
Есть еще один случай, в котором просто помещаются любые данные (без каких-либо проверок). Все проверки применяются к нему после его получения.
В то время как null как ключ, я думаю, можно использовать для определения некоторых данных по умолчанию. Обычно нуль как ключ не имеет большого смысла.
Ответ 5
Сэр HashMap также внутренне использует метод hashCode() для вставки элемента в HashMap, поэтому я думаю, что это будет неправильная причина для "почему HashTable разрешает нулевой ключ"
Ответ 6
Это упростит использование интерфейса карты/менее подробный. null
является законным значением для ссылочных типов. Создание карты, способной обрабатывать нулевые ключи и значения, устранит необходимость нулевой проверки перед вызовом api. Таким образом, карта api создает меньше "сюрпризов" во время выполнения.
Например, распространено, что карта будет использоваться для категоризации коллекции однородных объектов на основе одного поля. Когда карта совместима с нулем, код будет более кратким, поскольку это просто простой цикл без каких-либо операторов if (конечно, вам нужно убедиться, что коллекция не имеет нулевых элементов). Меньше строк кода без обработки ветвей/исключений будет более вероятно логически корректным.
С другой стороны, не разрешая null, интерфейс карты не станет лучше/безопаснее/проще использовать. Нецелесообразно полагаться на карту для отклонения нулей - это означает, что исключение будет выбрано, и вам придется поймать и обработать его. Или, чтобы избавиться от исключения, вам нужно будет убедиться, что перед вызовом методов карты ничего не пусто, и в этом случае вам все равно, если карта принимает значение null, поскольку вы все равно фильтровали вход.