Разница между HashMap, LinkedHashMap и TreeMap

959

В чем разница между HashMap, LinkedHashMapи TreeMapв Java? Я не вижу никакой разницы в результатах, так как все три имеют keySetи values. Что Hashtableс?

Map m1 = new HashMap();
m1.put("map", "HashMap");
m1.put("schildt", "java2");
m1.put("mathew", "Hyden");
m1.put("schildt", "java2s");
print(m1.keySet()); 
print(m1.values()); 

SortedMap sm = new TreeMap();
sm.put("map", "TreeMap");
sm.put("schildt", "java2");
sm.put("mathew", "Hyden");
sm.put("schildt", "java2s");
print(sm.keySet()); 
print(sm.values());

LinkedHashMap lm = new LinkedHashMap();
lm.put("map", "LinkedHashMap");
lm.put("schildt", "java2");
lm.put("mathew", "Hyden");
lm.put("schildt", "java2s");
print(lm.keySet()); 
print(lm.values());
Kevin
источник

Ответы:

1162

Все три класса реализуют Mapинтерфейс и предлагают в основном одинаковую функциональность. Наиболее важным отличием является порядок, в котором будет происходить итерация по записям:

  • HashMapне дает абсолютно никаких гарантий относительно порядка итераций. Он может (и будет) даже полностью меняться при добавлении новых элементов.
  • TreeMapбудет выполнять итерацию в соответствии с «естественным упорядочением» ключей в соответствии с их compareTo()методом (или внешним предоставлением Comparator). Кроме того, он реализует SortedMapинтерфейс, который содержит методы, которые зависят от этого порядка сортировки.
  • LinkedHashMap будет повторяться в том порядке, в котором записи были помещены в карту

«Hashtable» - это общее название для карт на основе хеша. В контексте Java API Hashtable- это устаревший класс со времен Java 1.1 до существования инфраструктуры коллекций. Его больше не следует использовать, поскольку его API перегружен устаревшими методами, дублирующими функциональность, а его методы синхронизированы (что может снизить производительность и, как правило, бесполезно). Используйте ConcurrentHashMap вместо Hashtable.

Майкл Боргвардт
источник
2
Что же такое Map на самом деле и в чем разница между Map, HashMap и Hashtables.
Кевин
5
@theband: карта - это интерфейс. HashMap и Hashtable оба реализуют это; как я уже писал, Hashtable - это устаревший класс.
Майкл Боргвардт
98
Заметная разница между Hashtableи HashMapзаключается в том, что в Hashtable «ни ключ, ни значение не могут быть нулевыми». Это ограничение не существует на последнем.
aioobe
4
@AshkanN: Да, на самом деле это стандартные способы сортировки. TreeMap имеет конструктор, который использует Comparator, и если он не предоставлен, он ожидает, что все объекты добавлены для реализации Comparable.
Майкл Боргвардт
4
Вы можете выбрать, хотите ли вы итерацию LinkedHashMap в порядке вставки или в порядке доступа.
lbalazscs
1608

Я предпочитаю визуальное представление:

╔══════════════╦═════════════════════╦═══════════════════╦═════════════════════╗
║   Property   ║       HashMap       ║      TreeMap      ║     LinkedHashMap   ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║ Iteration    ║  no guarantee order ║ sorted according  ║                     ║
║   Order      ║ will remain constant║ to the natural    ║    insertion-order  ║
║              ║      over time      ║    ordering       ║                     ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║  Get/put     ║                     ║                   ║                     ║
║   remove     ║         O(1)        ║      O(log(n))    ║         O(1)        ║
║ containsKey  ║                     ║                   ║                     ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║              ║                     ║   NavigableMap    ║                     ║
║  Interfaces  ║         Map         ║       Map         ║         Map         ║
║              ║                     ║    SortedMap      ║                     ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║              ║                     ║                   ║                     ║
║     Null     ║       allowed       ║    only values    ║       allowed       ║
║ values/keys  ║                     ║                   ║                     ║
╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣
║              ║   Fail-fast behavior of an iterator cannot be guaranteed      ║
║   Fail-fast  ║ impossible to make any hard guarantees in the presence of     ║
║   behavior   ║           unsynchronized concurrent modification              ║
╠══════════════╬═════════════════════╦═══════════════════╦═════════════════════╣
║              ║                     ║                   ║                     ║
║Implementation║      buckets        ║   Red-Black Tree  ║    double-linked    ║
║              ║                     ║                   ║       buckets       ║
╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣
║      Is      ║                                                               ║
║ synchronized ║              implementation is not synchronized               ║
╚══════════════╩═══════════════════════════════════════════════════════════════╝
Сергей Шевчик
источник
14
Помимо порядка вставки, LinkedHashMap также поддерживает порядок доступа (при использовании конструктора с логическим параметром порядка доступа).
Эяль Шнайдер
5
Дважды связанные ковши? Я думаю, что это добавляет ненужные накладные расходы на поиск сегмента для операций вставки / удаления (потому что он должен искать правильный интервал для помещения объекта). Я всегда думал, что реализации LinkedHashMap будут аналогичны реализациям Map, но с небольшими дополнительными издержками «списка записей» (может быть в виде связанного списка), который используется для целей итерации. Ты уверен, шевчик? Если да, можете ли вы объяснить или дать мне несколько онлайн-ссылок, подкрепляющих ваше заявление?
Саи Дуббака
5
@SaiDubbaka LinkedHashMap имеет двойные связанные сегменты, НО ТАКЖЕ есть таблица сегментов HashMap. Это не заменит его. Это означает, что доступ к сегментам осуществляется так же, как в HashMap, поскольку связанный список существует для итерации только в порядке вставки (или порядке доступа).
Херардо Ластра
5
Возможно, стоит упомянуть, что O (1) - лучший вариант сценария (который мы обычно не будем называть O, см. Этот вопрос )
Себастьян С
4
Также стоит отметить, что O (1) не всегда лучше, чем O (log n); если у вас очень длинный ключ, то что-то, основанное на BST, может быть намного быстрее, чем то, что должно выполнить хеширование O (n) всего ключа перед тем, как что-либо делать.
Фонд Моника иск
65

Все три представляют отображение от уникальных ключей к значениям и поэтому реализуют интерфейс Map .

  1. HashMap - это карта, основанная на хешировании ключей. Он поддерживает O (1) операции get / put. Ключи должны иметь последовательные реализации hashCode()иequals() для этого работать.

  2. LinkedHashMap очень похож на HashMap, но он добавляет понимание порядка, в котором элементы добавляются (или к которым осуществляется доступ), поэтому порядок итераций такой же, как порядок вставки (или порядок доступа, в зависимости от параметров построения).

  3. TreeMap - это древовидное отображение. Его операции put / get занимают O (log n) времени. Это требует, чтобы элементы имели некоторый механизм сравнения, либо с Comparable, либо с Comparator. Порядок итерации определяется этим механизмом.

Эяль Шнайдер
источник
1
Так что, если я правильно понимаю, единственное различие между LinkedHashMap и TreeMap заключается в производительности, учитывая, что порядок вставки такой же, как естественный порядок?
Моше Шахам
19
@MosheShaham Как он сказал в # 2: LinkedHashMapбудет повторяться в порядке вставки, а не в естественном порядке. Так что если вы добавите (2,5,3)к a LinkedHashMapи сделаете для каждого над ним, он вернется 2,5,3. Если бы 2,5,3к TreeMapон вернется 2,3,5.
Гринч
2
У древовидной карты также есть много других приятных трюков. Как карты головы и хвоста.
Томас Але
private TreeMap <String, Integer> mySection2 = new TreeMap <> (); mySection2.put ("abc1", 2); mySection2.put ( "abc2", 5); mySection2.put ( "ABC3", 3); for (Целое число x: mySection2.values ​​()) {Log.e ("LOG", "TreeMap ====" + x); } Это дает мне тот же порядок, что и элементы были вставлены? Пожалуйста, предложите, чем он отличается от LinkedHashMaps?
Б. Шрути
2
@ B.shruti: Это потому, что ваш порядок вставки соответствует лексикографическому порядку ваших ключей («abc1», «abc2», «abc3»). Если вы вставите в другом порядке, ваш код будет повторяться в соответствии с лексикографическим порядком.
Эяль Шнайдер
47

Посмотрите, где каждый класс находится в иерархии классов на следующей диаграмме ( больше ). TreeMap реализует, SortedMapа NavigableMapпока HashMapнет.

HashTableустарел и ConcurrentHashMapдолжен использоваться соответствующий класс. введите описание изображения здесь

pierrotlefou
источник
38

HashMap

  • Имеет пару значений (ключи, значения)
  • НЕТ значений ключа дублирования
  • неупорядоченный несортированный
  • он допускает один нулевой ключ и более одного нулевого значения

Хеш-таблица

  • так же, как хэш-карта
  • это не позволяет нулевые ключи и нулевые значения

LinkedHashMap

  • Упорядоченная версия реализации карты
  • На основе связанного списка и структур хеширования данных

TreeMap

  • Заказанная и отсортированная версия
  • основанный на хешировании структур данных
Прем Кумар
источник
3
Также HashTable синхронизируется. В любом случае, мне нравится ваш ответ, чистый и ясный.
Surasin Tancharoen
35

Еще немного информации из моего собственного опыта работы с картами, когда я буду использовать каждую из них:

  • HashMap - наиболее полезен при поиске наилучшей (быстрой) реализации.
  • TreeMap (интерфейс SortedMap) - наиболее полезен, когда я имею возможность сортировать или перебирать ключи в определенном порядке, который я определяю.
  • LinkedHashMap - сочетает в себе преимущества гарантированного заказа из TreeMap без увеличения стоимости обслуживания TreeMap. (Это почти так же быстро, как HashMap). В частности, LinkedHashMap также предоставляет отличную отправную точку для создания объекта Cache путем переопределения removeEldestEntry()метода. Это позволяет вам создать объект Cache, который может просрочить данные, используя определенные вами критерии.
Огрский псалом33
источник
10
Чтобы быть точным, TreeMap не поддерживает элементы в порядке. Держит ключи в порядке.
LS
17

Все три класса HashMap, TreeMapи LinkedHashMapреализует java.util.Mapинтерфейс, и представляют собой отображение уникального ключа для значений.

HashMap

  1. A HashMapсодержит значения, основанные на ключе.

  2. Он содержит только уникальные элементы.

  3. Может иметь один нулевой ключ и несколько нулевых значений.

  4. Это не поддерживает порядок .

    public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

LinkedHashMap

  1. A LinkedHashMapсодержит значения, основанные на ключе.
  2. Он содержит только уникальные элементы.
  3. Может иметь один нулевой ключ и несколько нулевых значений.
  4. Это то же самое, что HashMap, вместо этого поддерживает порядок вставки . // Смотрите замедление класса ниже

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>

TreeMap

  1. A TreeMapсодержит значения, основанные на ключе. Он реализует интерфейс NavigableMap и расширяет класс AbstractMap.
  2. Он содержит только уникальные элементы.
  3. Он не может иметь нулевой ключ, но может иметь несколько нулевых значений.
  4. Он такой же, как HashMapвместо этого, поддерживает восходящий порядок (сортируется с использованием естественного порядка его ключа.).

    public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable

Хеш-таблица

  1. Hashtable это массив списков. Каждый список известен как ведро. Положение сегмента определяется путем вызова метода hashcode (). Hashtable содержит значения, основанные на ключе.
  2. Он содержит только уникальные элементы.
  3. Возможно, у него нет нулевого ключа или значения.
  4. Это синхронизировано .
  5. Это унаследованный класс.

    public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable

Ссылка: http://javarevisited.blogspot.in/2015/08/difference-between-HashMap-vs-TreeMap-vs-LinkedHashMap-Java.html

roottraveller
источник
Обозначение Big-O в HashMap не должно быть O (1). Это лучший случай, и в хеш-таблицах в качестве наихудшего сценария используется O (n). Это подтверждается вашей ссылкой.
Хакон Лотвейт,
смотрите здесь - stackoverflow.com/questions/1055243/is-a-java-hashmap-really-o1/…
roottraveller
@ HaakonLøtveit Я также предлагаю пойти на фактический код здесь - grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/...
roottraveller
Это все еще говорит, что это O (N) в худшем случае. Это математическая концепция, и вы не можете сказать, что это O (1), если только это не O (1). Вы также предполагаете некоторые действительно хорошие функции хеширования здесь. Я имею в виду, мы могли бы использовать что-то вроде class TerribleHashKey {@Override hashCode () {return 4; / * Определяется справедливым броском игральных костей * /}} и используется в качестве ключа для других забавных вещей. Наличие высокой вероятности O (1) и наличие O (1) - это не одно и то же. Люди приходят сюда за помощью с домашней работой. Давайте не будем портить их оценки ..;)
Хакон Лотвейт
И стоит заметить, что в Java 8 у вас наихудший случай O (log (n)), если у вас более 8 сегментов, см. Grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk /… Для подробностей об этом.
Хакон Лотвейт,
14

HashMap дает абсолютно не гарантии о порядке итерации. Он может (и будет) даже полностью меняться при добавлении новых элементов. TreeMap будет выполнять итерацию в соответствии с «естественным порядком» ключей в соответствии с их методом compareTo () (или внешним компаратором). Кроме того, он реализует интерфейс SortedMap, который содержит методы, которые зависят от этого порядка сортировки. LinkedHashMap будет выполнять итерацию в порядке, в котором записи были помещены в карту

Посмотрите, как меняется производительность введите описание изображения здесь

Древовидная карта, которая является реализацией отсортированной карты. Сложность операции put, get и containsKey равна O (log n) из-за естественного упорядочения

Ручира Гаян Ранавира
источник
9

@Amit: SortedMapэто интерфейс, тогда TreeMapкак это класс, который реализует SortedMapинтерфейс. Это означает, что если следует протоколу, который SortedMapпросит его исполнителей сделать. Дерево, если оно не реализовано в виде дерева поиска, не может дать вам упорядоченные данные, потому что дерево может быть любым видом дерева. Таким образом, чтобы заставить TreeMap работать как порядок сортировки, он реализует SortedMap (например, дерево двоичного поиска - BST, сбалансированное BST, такое как AVL и дерево RB, даже дерево троичного поиска - в основном используется для итеративного поиска в упорядоченном виде).

public class TreeMap<K,V>
extends AbstractMap<K,V>
implements SortedMap<K,V>, Cloneable, Serializable

В NUT-SHELL HashMap: данные в O (1), без упорядочения

TreeMap : дает данные в O (log N), база 2. с упорядоченными ключами

LinkedHashMap: является хеш-таблицей со связным списком (например, indexed-SkipList) возможностью хранить данные так, как они вставляются в дерево. Лучше всего подходит для реализации LRU (используется в последнее время).

siddhusingh
источник
6

Ниже приведены основные различия между HashMap и TreeMap.

  1. HashMap не поддерживает порядок. Другими словами, HashMap не дает никакой гарантии, что элемент, вставленный первым, будет напечатан первым, где, как и TreeSet, элементы TreeMap также сортируются в соответствии с естественным порядком их элементов.

  2. Внутренняя реализация HashMap использует Hashing, а TreeMap внутренне использует реализацию Red-Black tree.

  3. HashMap может хранить один нулевой ключ и множество нулевых значений. TreeMap не может содержать нулевые ключи, но может содержать много нулевых значений.

  4. HashMap требует постоянной производительности по времени для основных операций, таких как get и put, т.е. O (1). Согласно документации Oracle, TreeMap обеспечивает гарантированную стоимость log (n) для метода get и put.

  5. HashMap намного быстрее, чем TreeMap, поскольку время выполнения HashMap является постоянным по отношению к времени журнала TreeMap для большинства операций.

  6. HashMap использует метод equals () для сравнения, а TreeMap использует метод compareTo () для поддержания порядка.

  7. HashMap реализует интерфейс Map, а TreeMap реализует интерфейс NavigableMap.

Виджей Барот
источник
5

Это разные реализации одного и того же интерфейса. Каждая реализация имеет свои преимущества и недостатки (быстрая вставка, медленный поиск) или наоборот.

Для получения дополнительной информации посмотрите на Javadoc TreeMap , HashMap , LinkedHashMap .

Тангенс
источник
Что такое Hashtables и чем они отличаются от карты?
Кевин
5

Хэш-карта не сохраняет порядок вставки.
Пример. Hashmap Если вы вставляете ключи как

1  3
5  9
4   6
7   15
3   10

Он может хранить его как

4  6
5  9
3  10
1  3
7  15

Связанный Hashmap сохраняет порядок вставки.

Пример.
Если вы вставляете ключи

1  3
5  9
4   6
7   15
3   10

Это будет хранить как

1  3
5  9
4   6
7   15
3   10

так же, как мы вставляем.

Древовидная карта хранит долины в порядке возрастания ключей. Пример.
Если вы вставляете ключи

1  3
5  9
4   6
7   15
3   10

Это будет хранить как

1  3
3  10
4   6
5   9
7   15
Шивам Шукла
источник
4
  • HashMap:

    • Порядок не поддерживается
    • Быстрее, чем LinkedHashMap
    • Используется для хранения кучи объектов
  • LinkedHashMap:

    • Порядок вставки LinkedHashMap будет поддерживаться
    • Медленнее, чем HashMap, и быстрее, чем TreeMap
    • Если вы хотите сохранить порядок ввода, используйте это.
  • TreeMap:

    • TreeMap - это древовидное отображение
    • TreeMap будет следовать естественному порядку ключей
    • Медленнее, чем HashMap и LinkedHashMap
    • Используйте TreeMap, когда вам нужно поддерживать естественный (по умолчанию) порядок
Premraj
источник
1

Все предлагают карту key-> value и способ перебирать ключи. Наиболее важным различием между этими классами являются временные гарантии и порядок ключей.

  1. HashMap предлагает 0 (1) поиск и вставку. Если вы перебираете ключи, порядок ключей по существу произвольный. Это реализовано массивом связанных списков.
  2. TreeMap предлагает O (log N) поиска и вставки. Ключи упорядочены, поэтому если вам нужно перебирать ключи в отсортированном порядке, вы можете. Это означает, что ключи должны реализовывать интерфейс Comparable. TreeMap реализуется с помощью красно-черного дерева.
  3. LinkedHashMap предлагает 0 (1) поиск и вставку. Ключи упорядочены по порядку их вставки. Это реализовано с помощью двусвязных сегментов.

Представьте, что вы передали пустой TreeMap, HashMap и LinkedHashMap в следующую функцию:

void insertAndPrint(AbstractMap<Integer, String> map) {
  int[] array= {1, -1, 0};
  for (int x : array) {
    map.put(x, Integer.toString(x));
  }
  for (int k: map.keySet()) {
   System.out.print(k + ", ");
  }
}

Вывод для каждого будет выглядеть так, как показано ниже.

Для HashMap выходные данные в моих собственных тестах были {0, 1, -1}, но это мог быть любой порядок. Там нет гарантии на заказ.
Древовидная карта, выходные данные были {-1, 0, 1}
LinkedList, выходные данные были {1, -1, 0}

Jitendra
источник
1

Хотя здесь есть много отличных ответов, я хотел бы представить свою собственную таблицу, описывающую различные Map реализации, связанные с Java 11.

Мы можем видеть эти различия, перечисленные на графике таблицы:

  • HashMapявляется универсальным, Map обычно используемым, когда у вас нет особых потребностей.
  • LinkedHashMapрасширяет HashMap, добавляя это поведение: Поддерживает порядок, порядок, в котором записи были первоначально добавлены . Изменение значения для ввода значения ключа не меняет его место в заказе.
  • TreeMapтакже поддерживает порядок, но использует либо (a) «естественный» порядок , означающий значение compareToметода для ключевых объектов, определенных в Comparableинтерфейсе, либо (b) вызывает предоставленнуюComparator вами реализацию .
    • TreeMapреализует как SortedMapинтерфейс, так и его преемник, NavigableMapинтерфейс.
  • NULL s: TreeMapэто не позволяют NULL в качестве ключа , а HashMap&LinkedHashMap делать.
    • Все три допускают NULL в качестве значения.
  • HashTableявляется наследием от Java 1 . Вытесняется ConcurrentHashMapклассом. Цитирование Javadoc: соответствует ConcurrentHashMapтой же функциональной спецификации Hashtable, что и включает версии методов, соответствующих каждому методу Hashtable.

Таблица реализаций карт в Java 11, сравнение их возможностей

Базилик Бурк
источник
0

HashMap
может содержать один нулевой ключ.

HashMap не поддерживает порядок.

TreeMap

TreeMap не может содержать нулевой ключ.

TreeMap поддерживает восходящий порядок.

LinkedHashMap

LinkedHashMap может использоваться для поддержания порядка вставки, при котором ключи вставляются в Map, или его также можно использовать для поддержания порядка доступа, к которому обращаются ключи.

Примеры ::

1) HashMap map = new HashMap ();

    map.put(null, "Kamran");
    map.put(2, "Ali");
    map.put(5, "From");
    map.put(4, "Dir");`enter code here`
    map.put(3, "Lower");
    for (Map.Entry m : map.entrySet()) {
        System.out.println(m.getKey() + "  " + m.getValue());
    } 

2) Карта TreeMap = новая TreeMap ();

    map.put(1, "Kamran");
    map.put(2, "Ali");
    map.put(5, "From");
    map.put(4, "Dir");
    map.put(3, "Lower");
    for (Map.Entry m : map.entrySet()) {
        System.out.println(m.getKey() + "  " + m.getValue());
    }

3) LinkedHashMap map = new LinkedHashMap ();

    map.put(1, "Kamran");
    map.put(2, "Ali");
    map.put(5, "From");
    map.put(4, "Dir");
    map.put(3, "Lower");
    for (Map.Entry m : map.entrySet()) {
        System.out.println(m.getKey() + "  " + m.getValue());
    }
Камран
источник
0

Наиболее важным среди всех трех является то, как они сохраняют порядок записей.

HashMap- Не сохраняет порядок записей. например.

public static void main(String[] args){
        HashMap<String,Integer> hashMap = new HashMap<>();
        hashMap.put("First",1);// First ---> 1 is put first in the map
        hashMap.put("Second",2);//Second ---> 2 is put second in the map
        hashMap.put("Third",3); // Third--->3 is put third in the map
        for(Map.Entry<String,Integer> entry : hashMap.entrySet())
        {
            System.out.println(entry.getKey()+"--->"+entry.getValue());
        }
    }

Выход для HashMap

LinkedHashMapСохраняет порядок, в котором были сделаны записи. например:

public static void main(String[] args){
        LinkedHashMap<String,Integer> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("First",1);// First ---> 1 is put first in the map
        linkedHashMap.put("Second",2);//Second ---> 2 is put second in the map
        linkedHashMap.put("Third",3); // Third--->3 is put third in the map
        for(Map.Entry<String,Integer> entry : linkedHashMap.entrySet())
        {
            System.out.println(entry.getKey()+"--->"+entry.getValue());
        }
    }

Выход LinkedHashMap

TreeMap: Сохраняет записи в порядке возрастания ключей. например:

public static void main(String[] args) throws IOException {
        TreeMap<String,Integer> treeMap = new TreeMap<>();
        treeMap.put("A",1);// A---> 1 is put first in the map
        treeMap.put("C",2);//C---> 2 is put second in the map
        treeMap.put("B",3); //B--->3 is put third in the map
        for(Map.Entry<String,Integer> entry : treeMap.entrySet())
        {
            System.out.println(entry.getKey()+"--->"+entry.getValue());
        }
    }

Вывод TreeMap

Анимеш Джайсвал
источник