Різниця між HashMap, LinkedHashMap та TreeMap


958

У чому різниця між HashMap, LinkedHashMapі TreeMapв Java? Я не бачу різниці у виході, оскільки всі три мають keySetі values. Що таке Hashtables?

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());

Відповіді:


1160

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

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

"Хештіл" - це загальна назва для хеш-карт. У контексті 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 має конструктор, який використовує компаратор для використання, і якщо його не передбачено, він очікує, що всі додані об’єкти реалізують Comparable.
Майкл Боргвардт

4
Ви можете вибрати, чи хочете ви ітерацію LinkedHashMap у порядку вставки чи порядку доступу.
lbalazscs

1606

Я віддаю перевагу візуальній презентації:

╔══════════════╦═════════════════════╦═══════════════════╦═════════════════════╗
║   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 також підтримує замовлення доступу (при використанні конструктора з булевим параметром замовлення доступу).
Eyal Schneider

5
Відра з подвійним зв'язком? Я думаю, що це додає зайвих накладних витрат на пошук відра для операцій вставки / вилучення (тому що він повинен шукати потрібне відро для розміщення об'єкта). Я завжди думав, що реалізація LinkedHashMap буде подібною до карти на Картах, але з невеликим додатковим накладним "списком записів" (може бути як пов'язаний список), який використовується для ітераційних цілей. Ви впевнені, шевчик? Якщо так, чи можете ви пояснити чи надати мені деякі посилання в Інтернеті, які підтримують вашу заяву?
Сай Дуббака

5
@SaiDubbaka LinkedHashMap має подвійні зв’язані відра, АЛЕ ТАКОЖ таблиця ковшів, яку має HashMap. Це не замінює його. Це означає, що доступ до відер робиться так само, як і в HashMap, оскільки зв'язаний список існує лише для ітерації в порядку вставки (або порядку доступу).
Джерардо Ластра

5
Можливо, варто згадати, що O (1) - найкращий сценарій (який ми зазвичай не називаємо O, див. Це запитання )
Sebastian S

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). Потрібно, щоб елементи мали певний механізм порівняння, як із Порівняльним, так і з Порівняльним. Порядок ітерації визначається цим механізмом.


1
Отже, якщо я правильно розумію, єдина відмінність між LinkedHashMap та TreeMap - це продуктивність, враховуючи, що порядок вставки такий же, як і природний порядок?
Моше Шахам

19
@MosheShaham Як він сказав у №2: чи LinkedHashMapбуде повторюватися в порядку вставки, а не в природному порядку. Тож якщо ви додасте (2,5,3)до а LinkedHashMapі зробите для кожного з них, воно повернеться 2,5,3. Якби 2,5,3до TreeMapвін повернеться 2,3,5.
усміхнувся

2
Карта дерева також має багато інших приємних хитрощів. Як карти голови та хвоста.
Томас Але

приватний TreeMap <String, Integer> mySection2 = новий TreeMap <> (); mySection2.put ("abc1", 2); mySection2.put ("abc2", 5); mySection2.put ("abc3", 3); for (Integer x: mySection2.values ​​()) {Log.e ("LOG", "TreeMap ====" + x); } Це дає мені той самий порядок, що і елементи, які були вставлені? Будь ласка, підкажіть, чим він відрізняється від LinkedHashMaps?
Б.шруті

2
@ B.shruti: Це тому, що порядок вставки відповідає лексикографічному порядку ваших ключів ("abc1", "abc2", "abc3"). Якщо ви вставите в іншому порядку, ваш код все одно буде повторюватися відповідно до лексикографічного впорядкування.
Eyal Schneider

47

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

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


38

HashMap

  • Він має парні значення (ключі, значення)
  • НЕ значення ключів дублювання
  • не упорядкований несортований
  • це дозволяє один нульовий ключ і більше одного нульового значення

HashTable

  • те саме, що і хеш-карта
  • він не дозволяє нульових ключів і нульових значень

LinkedHashMap

  • Це впорядкована версія реалізації карти
  • На основі пов'язаних структур списку та хешування даних

Дерево карта

  • Впорядкована та сортована версія
  • засновані на хеширующих структурах даних

3
Також HashTable синхронізований. У будь-якому випадку, мені подобається ваша відповідь, чітка і чітка.
Surasin Tancharoen

35

Ще трохи інформації з мого власного досвіду роботи з картами про те, коли я буду використовувати кожну:

  • HashMap - найкорисніший під час пошуку найкращої (швидкої) реалізації.
  • TreeMap (інтерфейс SortedMap) - Найкорисніший, коли я переживаю можливість сортування чи повторення клавіш у певному порядку, який я визначаю.
  • LinkedHashMap - поєднує переваги гарантованого замовлення з TreeMap без збільшення витрат на підтримку TreeMap. (Це майже так само швидко, як HashMap). Зокрема, LinkedHashMap також забезпечує чудову вихідну точку для створення об'єкта Cache шляхом переосмислення removeEldestEntry()методу. Це дозволяє створити об’єкт Кеш, який може закінчувати дані, використовуючи деякі визначені вами критерії.

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>

Дерево карта

  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 - це масив списку. Кожен список відомий як відро. Положення відра визначається за допомогою виклику методу хеш-коду (). 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


Позначення HashMap з великим розміром не повинно бути O (1). Це найкращий випадок, а хештелі мають O (n) як найгірший сценарій. Це підтримується вашим посиланням.
Haakon Løtveit


@ HaakonLøtveit Я також пропоную перейти до фактичного коду тут - grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
roottraveller

Цей СТИЛЬ каже, що це O (n) в гіршому випадку. Це математичне поняття, і ви не можете сказати, що це O (1), якщо це насправді O (1). Ви також припускаєте деякі дійсно хороші хеш-функції тут. Я маю на увазі, ми могли б використовувати щось на кшталт класу 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 /… Для детальної інформації про це.
Haakon Løtveit

14

HashMap абсолютно не гарантує порядку ітерації. Він може (і буде) навіть повністю змінюватися, коли додаються нові елементи. TreeMap буде повторювати відповідно до "природного впорядкування" клавіш за методом їх порівняння () (або компаратором, що постачається зовні). Крім того, він реалізує інтерфейс SortedMap, який містить методи, що залежать від цього порядку упорядкування. LinkedHashMap буде повторювати в тому порядку, в якому записи були розміщені на карті

Подивіться, як продуктивність змінюється .. введіть тут опис зображення

Карта дерева, яка є реалізацією сортованої карти. Складність операції put, get and containsKey становить O (log n) через природне впорядкування


9

@Amit: SortedMapце інтерфейс, тоді TreeMapяк клас, який реалізує SortedMapінтерфейс. Це означає, що якщо слід за протоколом, який SortedMapпросить його виконати. Дерево, якщо воно не реалізовано як дерево пошуку, не може надати вам упорядковані дані, оскільки дерево може бути будь-яким деревом. Отже, щоб TreeMap працював як сортований порядок, він реалізує SortedMap (наприклад, Binary Search Tree - BST, збалансований BST, як AVL та RB Tree, навіть Ternary Search Tree - в основному використовується для ітеративних пошуків впорядкованому способі).

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

У NUT-SHELL HashMap: дає дані в O (1), без впорядкування

TreeMap : дає дані в O (лог N), база 2. із упорядкованими ключами

LinkedHashMap: це таблиця Hash із пов'язаним списком (думаю про індексований SkipList), здатність зберігати дані таким чином, як вони вставляються в дерево. Найкраще підходить для впровадження LRU (принаймні недавно використовується).


6

Нижче наведені основні відмінності між HashMap і TreeMap

  1. HashMap не підтримує жодного порядку. Іншими словами, HashMap не дає жодної гарантії, що елемент, що вставляється спочатку, буде надрукований спочатку, де так само, як і TreeSet, елементи TreeMap також сортуються відповідно до природного впорядкування його елементів

  2. Внутрішня реалізація HashMap використовує Hashing та TreeMap, використовуючи внутрішньо Red-Black дерево.

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

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

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

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

  7. HashMap реалізує інтерфейс Map, тоді як TreeMap реалізує інтерфейс NavigableMap.


5

Це різні реалізації одного і того ж інтерфейсу. Кожна реалізація має деякі переваги та деякі недоліки (швидке вставлення, повільний пошук) або навпаки.

Детальніше дивіться на javadoc TreeMap , HashMap , LinkedHashMap .


Що таке Hashtables насправді і чим він відрізняється від Map.
Кевін

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 дотримуватиметься природного впорядкування ключів
    • Повільніше, ніж HashMap і LinkedHashMap
    • Використовуйте TreeMap, коли потрібно підтримувати природне (за замовчуванням) замовлення

1

Усі пропонують карту значень "ключ>>" та спосіб ітерації за допомогою клавіш. Найважливішою відмінністю між цими класами є гарантії часу та впорядкування ключів.

  1. HashMap пропонує 0 (1) пошук і вставлення. Якщо ви повторюєте клавіші, впорядкування клавіш по суті є довільним. Він реалізований масивом пов'язаних списків.
  2. TreeMap пропонує пошук і вставку O (log N). Клавіші впорядковані, тож якщо вам доведеться перебирати клавіші в упорядкованому порядку, ви можете. Це означає, що ключі повинні реалізовувати Порівняльний інтерфейс. Дерево-карту реалізовано Червоно-Чорним деревом.
  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}


1

Хоча тут є безліч відмінних відповідей, я хотів би представити свою власну таблицю з описом різних Mapреалізацій в комплекті з Java 11.

Ці відмінності ми бачимо на графіку таблиці:

  • HashMapє загальним призначенням, Map коли ви не маєте особливих потреб.
  • LinkedHashMapрозширюється HashMap, додаючи таку поведінку: Підтримує порядок, порядок, у якому записи були додані спочатку . Змінення значення для введення ключа-значення не змінює його місце в порядку.
  • TreeMapтеж підтримує порядок, але використовує або (а) «природний» порядок , тобто значення compareToметоди на ключових об'єктах визначаються на Comparableінтерфейс, або (б) викликає на 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 підтримує порядку зростання.

LinkedHashMap

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

Приклади :

1) HashMap map = новий 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 = нова 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.