HashMap、LinkedHashMap和TreeMap的区别

Java中的HashMapLinkedHashMapTreeMap有什么区别?我没有看到输出有任何区别,因为这三个都有keySetvaluesHashtables是什么?

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());
656072 次浏览

这些是同一接口的不同实现。每个实现都有一些优点和缺点(快速插入、缓慢搜索),反之亦然。

有关详细信息,请查看TreeMapHashMapLinkedHashMap的javadoc。

所有三个类都实现了Map接口并提供基本相同的功能。最重要的区别是对条目进行迭代的顺序:

  • HashMap对迭代顺序没有任何保证。当添加新元素时,它甚至可以(并且将会)完全改变。
  • TreeMap将根据键的compareTo()方法(或外部提供的Comparator)的“自然顺序”进行迭代。此外,它实现了#3接口,其中包含依赖于此排序顺序的方法。
  • LinkedHashMap将按照条目放入映射的顺序迭代

"哈希表"是基于哈希的映射的通用名称。在JavaAPI的上下文中,Hashtable是一个过时的类,从Java1.1开始,直到集合框架还没有出现。我们不应该再使用它,因为它的API中充斥着重复功能的过时方法,并且它的方法是同步的(这会降低性能并且通常毫无用处)。使用并发哈希表而不是Hashtable。

@Amit:SortedMap是一个接口,而TreeMap是一个实现SortedMap接口的类。这意味着如果遵循SortedMap要求其实现者做的协议。树除非实现为搜索树,否则不能给你有序的数据,因为树可以是任何类型的树。因此,为了使TreeMap像排序顺序一样工作,它实现了SortedMap(例如,二进制搜索树-BST,平衡BST,如AVL和R-B树,甚至三元搜索树-主要用于有序的迭代搜索)。

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

在螺母壳中HashMap:给出O(1)中的数据,没有排序

TreeMap:以O(log N)为基数2给出数据,具有有序键

LinkedHashMap:是具有链表(想想indexed-SkipList)功能的哈希表,以插入树的方式存储数据。最适合实现LRU(最近最少使用)。

HashMap

  • 它有对值(键,值)
  • 否重复键值
  • 无序无序
  • 它允许一个null键和多个null值

哈希表

  • 和hash map一样
  • 它不允许null键和null值

LinkedHashMap

  • 它是地图实现的有序版本
  • 基于链表和散列数据结构

TreeMap

  • 排序和排序版本
  • 基于哈希数据结构

只是一些更多的输入从我自己的经验与地图,当我将使用每一个:

  • HashMap-在寻找最佳性能(快速)实现时最有用。
  • TreeMap(SortedMap接口)-当我关心能够以我定义的特定顺序对键进行排序或迭代时,最有用。
  • LinkedHashMap-结合了从TreeMap保证排序的优势,而不会增加维护TreeMap的成本。(它几乎和HashMap一样快)。特别是,LinkedHashMap还通过覆盖#0方法为创建缓存对象提供了一个很好的起点。这允许您创建一个可以使用您定义的一些条件过期数据的缓存对象。

HashMap绝对不保证迭代顺序。它当添加新元素时,甚至可以(并且将会)完全改变。TreeMap将根据键的“自然顺序”迭代根据他们的compareTo()方法(或外部提供的比较器)。此外,它实现了SortedMap接口,其中包含依赖于此排序顺序的方法。LinkedHashMap将按照条目放入映射的顺序迭代

看看性能如何变化…在此处输入图片描述

树映射,是Sorted map的实现。由于自然排序,put、get和包含键操作的复杂度为O(log n)

我更喜欢视觉展示:

物业HashMapTreeMapLinkedHashMap
迭代顺序没有保证订单,将随着时间的推移保持不变按自然顺序排序插入顺序
获取/放置/删除/包含密钥O(1)O(log(n))O(1)
接口地图导航,地图,排序地图地图
空值/键允许唯一的价值观允许
快速失败行为无法保证迭代器的快速失效行为,在存在非同步并发修改的情况下无法做出任何硬保证无法保证迭代器的快速失效行为,在存在非同步并发修改的情况下无法做出任何硬保证无法保证迭代器的快速失效行为,在存在非同步并发修改的情况下无法做出任何硬保证
实施红黑树双联桶
已同步实现未同步实现未同步实现未同步

请参阅下图中每个类在类层次结构中的位置(更大的一个)。TreeMap实现了SortedMapNavigableMap,而HashMap没有。

HashTable已过时,应使用相应的ConcurrentHashMap类。在此处输入图片描述

都提供了键->值映射和遍历键的方法。之间最重要的区别这些类是时间保证和键的顺序。

  1. HashMap提供0(1)查找和插入。但是,如果您遍历键,则键本质上是任意的。它由链表数组实现。
  2. TreeMap提供O(log N)查找和插入。键是有序的,所以如果你需要迭代可以按顺序排列键。这意味着键必须实现可比较接口。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}

所有三个类HashMapTreeMapLinkedHashMap都实现了java.util.Map接口,并表示从唯一键到值的映射。

HashMap

  1. HashMap包含基于键的值。

  2. 它只包含独特的元素。

  3. 它可能有一个null键和多个null值。

  4. 它保持没有命令

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

LinkedHashMap

  1. LinkedHashMap包含基于键的值。
  2. 它只包含独特的元素。
  3. 它可能有一个null键和多个null值。
  4. 它与HashMap相同,而是维护插入顺序.//查看下面的类减速

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

树映射

  1. TreeMap包含基于键的值。它实现了NavigableMap接口并扩展了AbstractMap类。
  2. 它只包含独特的元素。
  3. 它不能有null键,但可以有多个null值。
  4. 它与HashMap相同,而是维护升序(使用其键的自然顺序排序)。

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

哈希表

  1. 哈希表是一个列表数组。每个列表都被称为一个桶。桶的位置通过调用hashcode()方法来识别。哈希表包含基于键的值。
  2. 它只包含独特的元素。
  3. 它可能没有任何null键或值。
  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
可以包含一个空键。

HashMap不维护任何顺序。

TreeMap

TreeMap不能包含任何null键。

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 map=new 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());}

哈希映射不保留插入顺序。
示例。哈希图如果您将键插入为

1  35  94   67   153   10

它可以存储为

4  65  93  101  37  15

链接哈希图保留插入顺序。

示例。
如果您正在插入键

1  35  94   67   153   10

它将存储为

1  35  94   67   153   10

和我们插入的一样。

树映射以键的递增顺序存储谷。示例。
如果您正在插入键

1  35  94   67   153   10

它将存储为

1  33  104   65   97   15

以下是HashMap和TreeMap的主要区别

  1. HashMap不维护任何顺序。换句话说,HashMap不提供任何保证,首先插入的元素将首先打印,其中与TreeSet一样,TreeMap元素也根据其元素的自然顺序进行排序

  2. 内部HashMap实现使用哈希,TreeMap内部使用红黑树实现。

  3. HashMap可以存储一个null键和许多null值。TreeMap不能包含null键,但可能包含许多null值。

  4. HashMap对于get和put即O(1)等基本操作需要恒定的时间性能。根据Oracle文档,TreeMap为get和put方法提供了保证的log(n)时间成本。

  5. HashMap比TreeMap快得多,因为对于大多数操作,HashMap的性能时间与日志时间TreeMap是恒定的。

  6. 相比之下,HashMap使用equals()方法,而TreeMap使用compareTo()方法来维护排序。

  7. HashMap实现了Map接口,而TreeMap实现了NaviggleMap接口。

  • HashMap:

    • 订单不维持
    • 比LinkedHashMap更快
    • 用于存储对象堆
  • LinkedHashMap:

    • LinkedHashMap插入顺序将被保留
    • 比HashMap慢,比TreeMap快
    • 如果要维护插入顺序,请使用此命令。
  • 树形图:

    • TreeMap是一个基于树的映射
    • TreeMap将遵循键的自然顺序
    • 比HashMap和LinkedHashMap慢
    • 当你需要维护自然(默认)顺序时使用TreeMap

这三者中最重要的是如何保存条目的顺序。

HashMap-不保存条目的顺序。例如。

public static void main(String[] args){HashMap<String,Integer> hashMap = new HashMap<>();hashMap.put("First",1);// First ---> 1 is put first in the maphashMap.put("Second",2);//Second ---> 2 is put second in the maphashMap.put("Third",3); // Third--->3 is put third in the mapfor(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 maplinkedHashMap.put("Second",2);//Second ---> 2 is put second in the maplinkedHashMap.put("Third",3); // Third--->3 is put third in the mapfor(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 maptreeMap.put("C",2);//C---> 2 is put second in the maptreeMap.put("B",3); //B--->3 is put third in the mapfor(Map.Entry<String,Integer> entry : treeMap.entrySet()){System.out.println(entry.getKey()+"--->"+entry.getValue());}}

TreeMap的输出

虽然这里有很多很好的答案,但我想展示我自己的表格,描述与Java11捆绑在一起的各种Map实现。

我们可以在图表中看到这些差异:

  • #0是你没有特殊需要时常用的通用#1
  • #0扩展了HashMap,添加了以下行为:维护顺序,条目最初添加的顺序。更改键值条目的值不会更改其在顺序中的位置。
  • #0也维护顺序,但使用(a)“自然”秩序,这意味着#2接口上定义的键对象上的#1方法的值,或者(b)调用您提供的a#3实现
    • TreeMap实现了#1接口及其后继者#2接口。
  • NULLs:TreeMapnot允许NULL作为键,而HashMapLinkedHashMap做。
    • 这三个都允许NULL作为值。
  • #0遗产。被#1类取代。引用Javadoc:ConcurrentHashMap遵循与Hashtable相同的功能规范,并包括与Hashtable的每个方法对应的方法版本。

Java11中的映射实现表,比较它们的特征