1. Обзор
В этом коротком уроке мы сосредоточимся на основных различиях между Хэш-таблицей и Хэш-картой .
2. Хэш-таблица и хэш-карта в Java
Hashtable и HashMap очень похожи – обе коллекции реализуют интерфейс Map .
Кроме того, методы put() , get() , remove () и containsKey() обеспечивают постоянную производительность O(1). Внутренне эти методы работают на основе общей концепции хэширования с использованием сегментов для хранения данных.
Ни один из классов не поддерживает порядок вставки элементов. Другими словами, первый добавленный элемент может не быть первым элементом, когда мы перебираем значения.
Но у них также есть некоторые различия, которые делают одно лучше другого в некоторых ситуациях. Давайте подробнее рассмотрим эти различия.
3. Различия между хэш-таблицей и хэш-картой
3.1. Синхронизация
Во-первых, Hashtable является потокобезопасным и может совместно использоваться несколькими потоками в приложении.
С другой стороны, HashMap не синхронизирован и не может быть доступен нескольким потокам без дополнительного кода синхронизации. Мы можем использовать Коллекции.synchronizedMap() для создания потокобезопасной версии HashMap . Мы также можем просто создать пользовательский код блокировки или сделать код потокобезопасным, используя ключевое слово synchronized .
HashMap не синхронизирован, поэтому он быстрее и использует меньше памяти, чем Hashtable . Как правило, несинхронизированные объекты работают быстрее, чем синхронизированные в однопоточном приложении.
3.2. Нулевые значения
Еще одним отличием является обработка null . HashMap позволяет добавлять одну Запись с null в качестве ключа, а также множество записей с null в качестве значения. Напротив, Hashtable не допускает null вообще . Давайте рассмотрим пример null и HashMap :
HashMapmap = new HashMap (); map.put(null, "value"); map.put("key1", null); map.put("key2", null);
Это приведет к:
assertEquals(3, map.size());
Далее давайте посмотрим, чем отличается хэш-таблица:
Hashtabletable = new Hashtable (); table.put("key", null);
Это приводит к исключению NullPointerException . Добавление объекта с null в качестве ключа также приводит к исключению NullPointerException :
table.put(null, "value");
3.3. Итерация По Элементам
HashMap использует Итератор для перебора значений, тогда как Hashtable имеет Перечислитель для того же самого. Итератор является преемником Перечислителя , что устраняет его несколько недостатков. Например, Iterator имеет метод remove() для удаления элементов из базовых коллекций.
Итератор – это быстрый итератор . Другими словами, он вызывает исключение ConcurrentModificationException , когда базовая коллекция изменяется во время итерации. Давайте рассмотрим пример fail-fast:
HashMapmap = new HashMap (); map.put("key1", "value1"); map.put("key2", "value2"); Iterator iterator = map.keySet().iterator(); while(iterator.hasNext()){ iterator.next(); map.put("key4", "value4"); }
Это вызывает исключение ConcurrentModificationException , потому что мы вызываем put() во время итерации по коллекции.
4. Когда следует выбрать HashMap Вместо Hashtable
Мы должны использовать HashMap для несинхронизированного или однопоточного приложения.
Стоит отметить, что начиная с JDK 1.8, Hashtable устарел. Тем не менее, ConcurrentHashMap является отличной заменой Hashtable . Мы должны рассмотреть ConcurrentHashMap для использования в приложениях с несколькими потоками.
5. Заключение
В этой статье мы проиллюстрировали различия между HashMap и Hashtable и то, что следует иметь в виду, когда нам нужно выбрать один из них.
Как обычно, реализация всех этих примеров и фрагментов кода закончена на Github .