Чем отличаются HashMap
и [Hashtable
][table] в Java?
Что эффективнее для непоточных приложений?
Есть несколько различий между 'HashMap' и 'Hashtable' на Яве:
'Hashtable' синхронизирован, тогда как 'HashMap' не. Это делает 'HashMap' лучше для непереплетенных заявлений, поскольку несинхронизированные Объекты, как правило, выступают лучше, чем синхронизированные.
'Hashtable' не позволяет 'пустые' ключи или ценности. 'HashMap' позволяет один 'пустой' ключ и любое количество 'пустых' ценностей.
Один из HashMap' s подклассы 'LinkedHashMap', поэтому если you' d хотят предсказуемый итеративный заказ (который является заказом вставки по умолчанию), Вы могли легко обменять 'HashMap' для 'LinkedHashMap'. Этот wouldn' t быть столь же легким, если Вы использовали 'Hashtable'.
Так как синхронизация не проблема для Вас, I' d рекомендуют 'HashMap'. Если синхронизация становится проблемой, Вы можете также посмотреть 'ConcurrentHashMap'.
Обратите внимание на то, что много ответов указывает, что Hashtable синхронизирован. На практике это покупает Вас очень мало. Синхронизация находится на accessor / методы мутатора остановят два добавления нитей или удаление из карты одновременно, но в реальном мире Вам часто будет нужна дополнительная синхронизация.
Очень общая идиома к " проверьте тогда put" — т.е. ищут вход в 'Карте' и добавляют его, если это уже не существует. Это ни в коем случае не атомная операция, используете ли Вы 'Hashtable' или 'HashMap'.
Эквивалентно синхронизированный 'HashMap' может быть получен:
Collections.synchronizedMap(myMap);
Но правильно осуществить эту логику Вам нужно дополнительная синхронизация формы:
synchronized(myMap) {
if (!myMap.containsKey("tomato"))
myMap.put("tomato", "red");
}
Даже повторяя по 'Hashtable '' s записи (или 'HashMap', полученный 'Collections.synchronizedMap'), не нить, безопасная, если Вы также не охраняете 'Карту' от того, чтобы быть измененным до дополнительной синхронизации.
Внедрения интерфейса 'ConcurrentMap' (например 'ConcurrentHashMap') решают часть этого включением , пронизывают безопасную семантику «проверка, тогда действуют» , такие как:
ConcurrentMap.putIfAbsent(key, value);
'Hashtable' считают устаревшим кодексом. There' s ничто о 'Hashtable' это can' t быть сделанным, используя 'HashMap' или происхождения 'HashMap', таким образом, для нового кодекса, я don' t видят любое оправдание за возвращение к 'Hashtable'.
Этот вопрос часто задают в интервью к проверке, понимает ли кандидат правильное использование классов коллекции и знает о доступных альтернативных решениях.
Примечание на некоторых важных условиях
HashMap может быть синхронизирован
'Карта m = Collections.synchronizeMap(hashMap)';
Карта обеспечивает взгляды Коллекции вместо прямой поддержки повторения через объекты Перечисления. Взгляды коллекции значительно увеличивают выразительность интерфейса, как обсуждено позже в этом разделе. Карта позволяет Вам повторять по ключам, ценностям или парам значения ключа; Hashtable не предоставляет третью возможность. Карта обеспечивает безопасный путь удалить записи посреди повторения; Hashtable не сделал. Наконец, Карта фиксирует незначительный дефицит в интерфейсе Hashtable. Hashtable назвали метод, содержит, который возвращается верный если Hashtable содержит данную стоимость. Данный его имя, you' d ожидают это метод, чтобы возвратиться верный, если Hashtable содержал данный ключ, потому что ключ - основной механизм доступа для Hashtable. Карта интерфейс устраняет этот источник беспорядка, переименовывая метод containsValue. Кроме того, это улучшает interface' s последовательность — containsValue параллелен containsKey.
'HashMap': внедрение интерфейса 'Map', который использует кодексы мешанины, чтобы внести множество в указатель. 'Hashtable': Привет, 1998 названный. Они хотят свой API коллекций назад.
Серьезно, хотя, you' ре более обеспеченное избегать 'Hashtable' в целом. Для одно-переплетенных приложений, Вы don' t нужно дополнительное наверху синхронизации. Для очень параллельных приложений параноидальная синхронизация могла бы привести к голоданию, тупикам или ненужным паузам сборки мусора. Как Тим Хоулэнд, на которого указывают, Вы могли бы использовать 'ConcurrentHashMap' вместо этого.
Следует иметь в виду, что 'HashTable' был устаревшим классом, прежде чем Java Collections Framework (JCF) была введена и была позже модифицирована, чтобы осуществить интерфейс 'Map'. Так были 'Вектор' и 'Стек'.
Поэтому всегда держитесь подальше от них в новом кодексе с тех пор там всегда лучшая альтернатива в JCF , как указали другие.
Вот явская шпаргалка коллекции, что Вы найдете полезным. Заметьте, что серый блок содержит устаревший класс HashTable, Вектор и Стек.
Есть многие хороший ответ, уже опубликованный. I' m добавляющий немного новых пунктов и суммирующий его.
'HashMap' и 'Hashtable' и используются, чтобы сохранить данные в ключе и оценить form. Оба используют метод хеширования, чтобы сохранить уникальные ключи. Но есть много различий между классами HashMap и Hashtable, которые даны ниже.
HashMap
Hashtable
Дополнительные материалы для чтения Что такое различие между HashMap и Hashtable на Яве?
В дополнение к тому, что сказал izb, 'HashMap' позволяет нулевые значения, тогда как 'Hashtable' не делает.
Также обратите внимание, что 'Hashtable' расширяет класс 'Словаря', который как государство Javadocs, является устаревшим и был заменен интерфейсом 'Map'.
Смотрите на эту диаграмму. Это обеспечивает сравнения между различными структурами данных наряду с HashMap и Hashtable. Сравнение точно, ясно и легко понять.
[Явская матрица коллекции] [1]
[1]: https://docs.google.com/spreadsheet/pub? key=0Aq3e8BiuZY2wdFpHSlV0QzVmV1lUNHJidGd2b0Zrb3c& single=true& gid=0& output=pdf
Hashtable
похожа на HashMap
и имеет аналогичный интерфейс. Рекомендуется использовать HashMap
, если только вам не требуется поддержка старых приложений или вам нужна синхронизация, поскольку методы Hashtables
синхронизированы. Так что в вашем случае, поскольку вы не используете многопоточность, лучше всего использовать HashMap
.
Около всех других важных аспектов, уже упомянутых здесь, API Коллекций (например, интерфейс Map) изменяется все время, чтобы соответствовать " последний и greatest" дополнения к Явской спекуляции.
Например, сравните Яву 5 повторений Карты:
for (Elem elem : map.keys()) {
elem.doSth();
}
против старого подхода Hashtable:
for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
Elem elem = (Elem) en.nextElement();
elem.doSth();
}
На Яве 1.8 нам также обещают быть в состоянии построить и получить доступ к HashMaps как на старых добрых языках сценариев:
Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];
Обновление: Нет, они won' t приземляются в 1,8...: (
Другое основное отличие между hashtable и hashmap - то, что Iterator в HashMap - быстрый потерпевший неудачу, в то время как счетчик для Hashtable не и бросок ConcurrentModificationException, если Нить изменяет карту структурно, добавляя или удаляя какой-либо элемент кроме Iterator' s собственный удаляют () метод. Но это не гарантируемое поведение и будет сделано JVM на лучшем усилии "
Мой источник: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html
У 'HashMap' и 'Hashtable' есть значительные алгоритмические различия также. Никто не упомянул это прежде так that' s, почему я поднимаю его. 'HashMap' построит хеш-таблицу с силой двух размеров, увеличит его динамично таким образом, что Вы имеете самое большее приблизительно восемь элементов (столкновения) в любом ведре и размешаете элементы очень хорошо для общих типов элемента. Однако внедрение 'Hashtable' обеспечивает лучше и более прекрасный контроль над хешированием, если Вы знаете то, что Вы делаете, а именно, Вы можете зафиксировать использование размера стола, например, самое близкое простое число к Вашему размеру области ценностей, и это приведет к лучшей работе, чем HashMap т.е. меньше столкновений для некоторых случаев.
Отдельный от очевидных различий, обсужденных экстенсивно в этом вопросе, я рассматриваю Hashtable как " руководство drive" автомобиль, где Вы имеете лучший контроль над хешированием и HashMap как " автоматический drive" копия, которая будет обычно выступать хорошо.
HashTable синхронизирован, если Вы используете его в единственной нити, Вы можете использовать HashMap, который является несинхронизированной версией. Несинхронизированные объекты часто немного более производительны. Между прочим, если несколько нитей получают доступ к HashMap одновременно, и по крайней мере одна из нитей изменяет карту структурно, это должно быть синхронизировано внешне. Youn может обернуть несинхронизированную карту в синхронизированное использование:
Карта m = Collections.synchronizedMap (новый HashMap (...));
HashTable может только содержать непустой объект как ключ или как стоимость. HashMap может содержать пустые значения ключа и нулевые значения.
iterators, возвращенные Картой, являются быстрым потерпевшим неудачу, если карта структурно изменена когда-либо после того, как iterator создан, в любом случае кроме через iterator' s собственный удаляют метод, iterator бросит 'ConcurrentModificationException'. Таким образом, перед лицом параллельной модификации, iterator терпит неудачу быстро и чисто, вместо того, чтобы рискнуть произвольным, недетерминированным поведением в неопределенное время в будущем. Принимая во внимание, что Перечисления, возвращенные Hashtable' s ключи и методы элементов не являются быстрым потерпевшим неудачу.
HashTable и HashMap - член Явская Структура Коллекций (так как Ява 2 платформы v1.2, HashTable был модифицирован, чтобы осуществить интерфейс Map).
HashTable считают устаревшим кодексом, документация советуют, чтобы использовать ConcurrentHashMap вместо Hashtable, если безопасное от нити высоко параллельное внедрение желаемо.
HashMap doesn' t гарантируют заказ, в котором возвращены элементы. Для HashTable я предполагаю it' s то же, но I' m не совсем уверенный, я don' t находят ресурс, который это ясно указывает этому.
Основываясь на информации здесь, я бы рекомендовал использовать HashMap. Я думаю, самое большое преимущество заключается в том, что Java не позволит вам изменять его во время итерации, если только вы не делаете это через итератор.
« Суперкласс, Наследие и участник Структуры Коллекции Hashtable - устаревший класс, введенный в 'JDK1.0', который является подклассом класса Словаря. От 'JDK1.2' Hashtable повторно спроектирован, чтобы осуществить [Интерфейс Map] (https://docs.oracle.com/javase/tutorial/collections/interfaces/map.html), чтобы сделать члена структуры коллекции. HashMap - член Явской Структуры Коллекции с самого начала ее введения в 'JDK1.2'. HashMap - подкласс класса AbstractMap. <! - язык - все: lang-Ява - >
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
<! - язык - все: lang-Ява - > « Начальная способность и Коэффициент нагрузки Способность - количество ведер в хеш-таблице, и начальная способность - просто способность в то время, когда хеш-таблица создана. Обратите внимание, что хеш-таблица открыта: в случае " 'мешанина' ['столкновение'] (http://www.algolist.net/Data_structures/Hash_table/Chaining) " единственное ведро хранит многократные въезды, которые должны быть обысканы последовательно. Коэффициент нагрузки - мера того, как полный хеш-таблице позволяют добраться, прежде чем ее способность будет автоматически увеличена.
HashMap строит пустую хеш-таблицу со способностью начальной буквы по умолчанию (16) и коэффициент нагрузки по умолчанию (0.75). Где, поскольку Хэштэйбл строит пустой hashtable со способностью начальной буквы по умолчанию (11) , и коэффициент нагрузки / заполняют отношение (0.75). ! [Карта мешанины & Hashtable] [1] « Структурная модификация в случае столкновения мешанины _ 'HashMap', 'Hashtable' в случае столкновений мешанины они хранят записи карты в связанных списках. От Java8 для 'HashMap' , если ведро мешанины растет вне определенного порога, то ведро переключится с ['связанный список записей в сбалансированное дерево'] (http://openjdk.java.net/jeps/180). которые улучшаются, работа худшего случая от O (n) к O (зарегистрируйте n). Преобразовывая список в двоичное дерево, hashcode используется в качестве ветвящейся переменной. Если есть два различных hashcodes в том же ведре, каждого считают больше и идет направо от дерева и другого налево. Но когда оба, hashcodes равны, 'HashMap', предполагают, что ключи сопоставимы, и сравнивает ключ, чтобы определить направление так, чтобы некоторый порядок мог быть поддержан. Это - хорошая практика, чтобы сделать ключи 'HashMap' [сопоставимыми] (https://stackoverflow.com/a/31244596/5081877). На добавляющих записях, если размер ведра достигает 'TREEIFY_THRESHOLD =, 8' новообращенных связали список записей в сбалансированное дерево при удалении записей меньше, чем 'TREEIFY_THRESHOLD' и самое большее 'UNTREEIFYTHRESHOLD = 6' повторно преобразуют сбалансированное дерево в связанный список записей. < sup> [Ява 8 SRC] (http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/HashMap.java#l244), [stackpost] (https://stackoverflow.com/a/43911638/5081877) « повторение представления Коллекции, Быстрый Потерпевший неудачу и Предохранительный
+--------------------+-----------+-------------+
| | Iterator | Enumeration |
+--------------------+-----------+-------------+
| Hashtable | fail-fast | safe |
+--------------------+-----------+-------------+
| HashMap | fail-fast | fail-fast |
+--------------------+-----------+-------------+
| ConcurrentHashMap | safe | safe |
+--------------------+-----------+-------------+
['Iterator'] (https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html) является быстрым потерпевшим неудачу по своей природе. т.е. это бросает ConcurrentModificationException, если коллекция изменена, в то время как повторение кроме своего собственного удаляет () метод. Где как ['Перечисление'] (https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html) предохранительное по своей природе. Это не бросает исключений, если коллекция изменена, повторяя. По словам Явских Докторов API, Iterator всегда предпочитается по Перечислению.
< sub> < b> NOTE: функциональность интерфейса Enumeration дублирована интерфейсом Итерэтора. Кроме того, Итерэтор добавляет, что дополнительное удаляет операцию, и имеет более короткие названия метода. Новые внедрения должны рассмотреть использование Итерэтора в предпочтении к Перечислению В [Ява 5 введенных Интерфейсов ConcurrentMap] (https://docs.oracle.com/javase/8/docs/technotes/guides/collections/changes5.html): 'ConcurrentHashMap' - очень параллельное, высокоэффективное внедрение 'ConcurrentMap', поддержанное хеш-таблицей. Это внедрение никогда не блокирует, выполняя поиск и позволяет клиенту выбирать уровень параллелизма для обновлений. Это предназначено как общедоступная замена для 'Hashtable': в дополнение к осуществлению 'ConcurrentMap' это поддерживает все " legacy" методы, специфичные для 'Hashtable'.Стоимость каждого 'HashMapEntry [изменчива] (https://stackoverflow.com/a/47695757/5081877), таким образом, обеспечение мелкозернистой последовательности для модификаций, с которыми спорят, и последующий читает; каждый прочитанный отражает последний раз законченное обновление
Iterators и Enumerations, Терпят неудачу Безопасный - отражение государства в какой-то момент начиная с создания iterator/enumeration; это допускает одновременный, читает и модификации за счет уменьшенной последовательности. Они не бросают ConcurrentModificationException. Однако iterators разработаны, чтобы использоваться только одной нитью за один раз.
Like 'Hashtable', но в отличие от 'HashMap', этот класс не позволяет пустому указателю использоваться в качестве ключа или оценивает.
<! - язык - все: lang-Ява - >
public static void main(String[] args) {
//HashMap<String, Integer> hash = new HashMap<String, Integer>();
Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
//ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();
new Thread() {
@Override public void run() {
try {
for (int i = 10; i < 20; i++) {
sleepThread(1);
System.out.println("T1 :- Key"+i);
hash.put("Key"+i, i);
}
System.out.println( System.identityHashCode( hash ) );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
new Thread() {
@Override public void run() {
try {
sleepThread(5);
// ConcurrentHashMap traverse using Iterator, Enumeration is Fail-Safe.
// Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
sleepThread(1);
System.out.println("T2 : "+ e.nextElement());
}
// HashMap traverse using Iterator, Enumeration is Fail-Fast.
/*
for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
sleepThread(1);
System.out.println("T2 : "+ it.next());
// ConcurrentModificationException at java.util.Hashtable$Enumerator.next
}
*/
/*
Set< Entry<String, Integer> > entrySet = hash.entrySet();
Iterator< Entry<String, Integer> > it = entrySet.iterator();
Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
while( entryEnumeration.hasMoreElements() ) {
sleepThread(1);
Entry<String, Integer> nextElement = entryEnumeration.nextElement();
System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
//java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
// at java.util.HashMap$EntryIterator.next
// at java.util.Collections$3.nextElement
}
*/
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
try {
unmodifiableMap.put("key4", "unmodifiableMap");
} catch (java.lang.UnsupportedOperationException e) {
System.err.println("UnsupportedOperationException : "+ e.getMessage() );
}
}
static void sleepThread( int sec ) {
try {
Thread.sleep( 1000 * sec );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
<! - язык - все: lang-Ява - > « пустые ключи и нулевые значения 'HashMap' позволяет максимуму один пустой ключ и любое количество нулевых значений. То, где, поскольку 'Hashtable' не позволяет даже единственное пустое значение ключа и нулевое значение, если ключ или оценивает пустой указатель, тогда, это бросает NullPointerException. < sup> [Пример] (https://stackoverflow.com/a/31243387/5081877)
@See
Для переплетенных приложений Вам может часто сходить с рук ConcurrentHashMap-, зависит от Ваших эксплуатационных требований.
'Hashmap' и 'HashTable' и хранят ключ и стоимость.
'Hashmap' может сохранить один ключ как 'пустой указатель'. 'Hashtable' can' t хранят 'пустой указатель'.
'HashMap' не синхронизирован, но 'Hashtable' синхронизирован.
'HashMap' может быть синхронизирован с 'Коллекцией. SyncronizedMap (карта)'
Map hashmap = new HashMap();
Map map = Collections.SyncronizedMap(hashmap);
Кроме различий, уже упомянутых, нужно отметить, что начиная с Явы 8, 'HashMap' динамично заменяет Узлы (связанный список) используемый в каждом ведре с TreeNodes (красно-черное дерево), так, чтобы, даже если высоко крошат столкновения, существовали, худший случай , когда поиск
O (регистрация (n)) для 'HashMap' против O (n) в 'Hashtable'.
*К вышеупомянутому улучшению еще не относились 'Hashtable', но только к 'HashMap', 'LinkedHashMap' и 'ConcurrentHashMap'.
К вашему сведению, в настоящее время,