关于Java:HashMap、LinkedHashMap和TreeMap的差异

Difference between HashMap, LinkedHashMap and TreeMap

在Java中EDCOX1与0、EDCX1、1和EDCX1 2的区别是什么?我看不出输出有什么不同,因为这三个都有keySetvalues。什么是Hashtables?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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());

我喜欢视觉展示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
╔══════════════╦═════════════════════╦═══════════════════╦═════════════════════╗
║   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               ║
╚══════════════╩═══════════════════════════════════════════════════════════════╝


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

  • HashMap对迭代顺序绝对没有保证。当添加新元素时,它甚至可以(也将)完全改变。
  • TreeMap将根据密钥的"自然排序"根据它们的compareTo()方法(或外部提供的Comparator方法)进行迭代。此外,它还实现了SortedMap接口,其中包含依赖于此排序顺序的方法。
  • LinkedHashMap将按条目放入地图的顺序迭代。

"hashtable"是基于哈希的映射的通用名称。在Java API的上下文中,在集合框架存在之前,从1.1 Java时代开始,EDCOX1 9是一个过时的类。它不应该再被使用了,因为它的API中充斥着重复功能的过时方法,并且它的方法是同步的(这会降低性能,通常是无用的)。使用ConcurrentHashMap而不是HashTable。


这三个都表示从唯一键到值的映射,因此实现了映射接口。

  • hashmap是基于键散列的映射。它支持O(1)获取/输出操作。密钥必须具有一致的hashCode()equals()的实现,这样才能工作。

  • linkedhashmap与hashmap非常相似,但它增加了对添加(或访问)项的顺序的认识,因此迭代顺序与插入顺序(或访问顺序,取决于构造参数)相同。

  • treemap是基于树的映射。它的输入/获取操作需要O(log n)时间。它要求项目具有某种比较机制,可以使用比较器或比较器。迭代顺序由这个机制决定。


  • 在下图中查看每个类在类层次结构中的位置(较大的一个)。treemap执行SortedMapNavigableMap,而HashMap不执行。

    HashTable已过时,应使用相应的ConcurrentHashMap类。enter image description here


    哈希图

    • 它有对值(键、值)
    • 无重复键值
    • 无序未排序
    • 它允许一个空键和多个空值

    散列表

    • 与哈希图相同
    • 它不允许空键和空值

    链接地图

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

    树图

    • 订购和分类版本
    • 基于哈希数据结构


    只是从我自己的地图经验中得到更多的信息,关于我何时使用每个地图:

    • hashmap-在寻找最佳性能(快速)实现时最有用。
    • treemap(sortedmap interface)——当我考虑到能够按照我定义的特定顺序对键进行排序或迭代时最有用。
    • Linkedhashmap-结合了保证从TreeMap订购的优点,而不增加维护TreeMap的成本。(几乎和哈希图一样快)。尤其是,linkedhashmap还提供了通过重写removeEldestEntry()方法来创建缓存对象的一个很好的起点。这允许您创建一个缓存对象,该对象可以使用您定义的某些条件使数据过期。


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

    哈希图

  • HashMap包含基于键的值。

  • 它只包含唯一的元素。

  • 它可以有一个空键和多个空值。

  • 它没有维持秩序。

    public class HashMap extends AbstractMap implements Map, Cloneable, Serializable

  • 链接地图

  • LinkedHashMap包含基于键的值。
  • 它只包含唯一的元素。
  • 它可以有一个空键和多个空值。
  • 它与hashmap相同,而维护插入顺序。//见下面的减速等级

    public class LinkedHashMap extends HashMap implements Map

  • 树图

  • TreeMap包含基于键的值。它实现了navigablemap接口并扩展了abstractmap类。
  • 它只包含唯一的元素。
  • 它不能有空键,但可以有多个空值。
  • 它与HashMap相同,而保持升序(使用其键的自然顺序排序)。

    public class TreeMap extends AbstractMap implements NavigableMap, Cloneable, Serializable

  • 哈希表

  • 哈希表是一个列表数组。每个列表都被称为bucket。通过调用hashcode()方法来标识bucket的位置。哈希表包含基于键的值。
  • 它只包含唯一的元素。
  • 它可能没有任何空键或值。
  • 它是同步的。
  • 它是一个传统类。

    public class Hashtable extends Dictionary implements Map, Cloneable, Serializable

  • ></P><P>参考:http://javarevisited.blogspot.in/2015/08/difference-between-hashmap-vs-treemap-vs-linkedhashmap-java.html</P></p>
<div class=


    HashMap makes absolutely not guarantees about the iteration order. It
    can (and will) even change completely when new elements are added.
    TreeMap will iterate according to the"natural ordering" of the keys
    according to their compareTo() method (or an externally supplied
    Comparator). Additionally, it implements the SortedMap interface,
    which contains methods that depend on this sort order. LinkedHashMap
    will iterate in the order in which the entries were put into the map

    看看性能如何变化……enter image description here

    树映射,是排序映射的一种实现。由于自然排序,Put、Get和ContainsKey操作的复杂性为O(log n)。


    @amit:SortedMap是接口,而TreeMap是实现SortedMap接口的类。这意味着如果遵循SortedMap要求其实现者执行的协议。树除非实现为搜索树,否则不能为您提供有序的数据,因为树可以是任何类型的树。因此,为了使treemap像排序顺序一样工作,它实现了sortedmap(例如二进制搜索树-bst,平衡的bst-like avl和r-b树,甚至三元搜索树-主要用于有序的迭代搜索)。

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

    坚果壳HashMap:在o(1)中给出数据,不排序

    TreeMap:以o(log n)为单位给出数据,基2。带有序钥匙

    LinkedHashMap是一个哈希表,具有链表(考虑索引的skiplist)功能,能够以插入树的方式存储数据。最适合实施LRU(最近使用最少)。


    以下是hashmap和treemap之间的主要区别

  • hashmap不维护任何顺序。换言之,hashmap不保证首先插入的元素会被打印出来,就像treeset一样,treemap元素也会按照元素的自然顺序排序。

  • 内部hashmap实现使用散列,treemap内部使用红黑树实现。

  • 哈希映射可以存储一个空键和多个空值。TreeMap不能包含空键,但可以包含多个空值。

  • hashmap对get和put等基本操作(即o(1))采用恒定的时间性能,根据Oracle文档,treemap为get和put方法提供了保证的日志(n)时间成本。

  • hashmap比treemap快得多,因为对于大多数操作,hashmap的性能时间与日志时间treemap相比是恒定的。

  • hashmap使用equals()方法进行比较,treemap使用compareto()方法维护顺序。

  • hashmap实现映射接口,treemap实现navigablemap接口。


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

    有关详细信息,请查看treemap、hashmap、linkedhashmap的javadoc。


    • HashMap:

      • 订单未维护
      • 比Linkedhashmap快
      • 用于存储对象堆
    • LinkedHashMap:

      • 将维护LinkedHashMap插入顺序
      • 比hashmap慢,比treemap快
      • 如果要保持插入顺序,请使用此选项。
    • TreeMap:

      • treemap是基于树的映射
      • Treemap将遵循键的自然顺序
      • 比hashmap和linkedhashmap慢
      • 需要保持自然(默认)排序时使用treemap

    哈希映射不保留插入顺序。例子。散列图如果插入的键为

    1
    2
    3
    4
    5
    1  3
    5  9
    4   6
    7   15
    3   10

    它可以存储为

    1
    2
    3
    4
    5
    4  6
    5  9
    3  10
    1  3
    7  15

    链接的hashmap保留插入顺序。

    例子。如果你在插入钥匙

    1
    2
    3
    4
    5
    1  3
    5  9
    4   6
    7   15
    3   10

    它将存储为

    1
    2
    3
    4
    5
    1  3
    5  9
    4   6
    7   15
    3   10

    和我们插入的一样。

    树图按键的递增顺序存储山谷。例子。如果你在插入钥匙

    1
    2
    3
    4
    5
    1  3
    5  9
    4   6
    7   15
    3   10

    它将存储为

    1
    2
    3
    4
    5
    1  3
    3  10
    4   6
    5   9
    7   15

    它们都提供了一个键->值映射和一种迭代键的方法。最重要的区别在于这些类是时间保证和键的顺序。

  • hashmap提供0(1)查找和插入。但是,如果您遍历键,则键本质上是任意的。它由一个链表数组实现。
  • treemap提供O(log n)查找和插入。键是有序的,因此如果需要迭代按顺序排列的键,可以。这意味着键必须实现可比较的interface.treemap由红黑树实现。
  • LinkedHashMap提供0(1)查找和插入。键按插入顺序排列。它是由双链接存储桶实现。
  • 假设您将空的treemap、hashmap和linkedhashmap传递到以下函数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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,但它可以是任何顺序。没有保证排序。Treemap,输出是,-1,0,1LinkedList,输出为,1,-1,0_


    哈希图不能包含一个空键。

    hashmap不维护任何顺序。

    树图

    treemap不能包含任何空键。

    Treemap保持升序。

    链接地图

    linkedhashmap可以用来维护插入顺序,在这个顺序上键被插入到映射中,或者也可以用来维护访问顺序,在这个顺序上键被访问。

    实例:

    1)hashmap=new hashmap();

    1
    2
    3
    4
    5
    6
    7
    8
        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();

    1
    2
    3
    4
    5
    6
    7
    8
        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=new linkedhashmap();

    1
    2
    3
    4
    5
    6
    7
    8
        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());
        }