【问题标题】:difference between linkedhashmap, hashmap, map, hashtablelinkedhashmap、hashmap、map、hashtable的区别
【发布时间】:2011-06-17 07:46:37
【问题描述】:

我正在为软件面试做准备,但我被一个问题困扰了好几天。

我无法弄清楚 Java Collection API 中的linkedhashmap、map、hashtable、hashmap 之间的区别。

所有这些都具有相同的 get 和 put 复杂性吗?我知道地图是接口类 而hashmap、hashtable、linkedhashmap实现了这个接口。那么这是否意味着这 3 个类的内部实现是相同的呢?它们在 collections api 中是如何实现的?

提前致谢!!!

【问题讨论】:

  • 使用LinkedHashMap,它基本上是一个链表它非常快速的搜索。 HashMap 是哈希表(基于树,pow2 桶大小)的糟糕实现,它在迭代时更差,在搜索时平庸。 Hashtable 是最古老的 impl。带一些同步。 IdentityHashMap 应该是哈希表 impl 应该是什么,可惜它仅适用于身份 (==) 和 identityHashcode

标签: java collections


【解决方案1】:

我怀疑这些差异的解释比 JavaDocs 中已经为这些类编写的要好得多:

  • Map 是所有这些类通用的基本接口
  • Hashtable 是该接口的一种实现,在“旧”时代,人们认为同步所有内容是个好主意(参考 Vector)。如果您知道自己在做什么,它会提供“某种”线程安全。如果您对可以在多个线程中使用的地图很认真,您绝对应该查看ConcurrentHashMapConcurrentSkipListMap
  • HashMap 与 Hashtable 几乎相同,但删除了同步。它是首选的通用 Map 实现。
  • LinkedHashMap 还维护其条目的链接列表,允许维护排序或轻松将其用作 LRU 缓存,只需阅读 JavaDoc。

前面提到的所有Map 实现都具有(摊销)O(1) 时间复杂度的基本 get/put 操作。 null 值的处理存在细微差别,详情请查看 JavaDoc。

要了解这些类是如何实现的,请查看它们的继承树:

  • Map(只是界面)
    • Dictionary(已过时的抽象类)
      • Hashtable(“旧”地图实现独立存在)
    • AbstractMap(“新”地图实现的基本功能)
      • HashMap(第一个通用的具体地图实现)
        • LinkedHashMap(通过维护链表扩展HashMap

【讨论】:

  • 哈希表扩展了字典顺便说一句。字典现在是一个很没用的抽象类,没人关注。 HashMap 和 Hashrable 之间的区别(除了明显的同步)是桶数组的大小。 HashMap 使用了 pow2 并且可以使用 hash&(table.length-1) 比 Hashtable (hash & 0x7FFFFFFF) % tab.length 更快
  • 抽象类可以实现接口吗?
  • @Amm 是的,你可以让每个类抽象,如果它根本没有任何抽象方法的话。
  • 我还认为理想的表格长度是素数?
  • @Amm,在简单的情况下是的,但是HashMap has been reimplemented in Java4,使用更复杂的算法,要求地图大小始终是 2 的幂。
【解决方案2】:

它们都遵守相同的合同,但在实现上存在一些差异:

  • LinkedHashMap:键按插入顺序维护
  • HashTable:所有操作都是同步的,没有顺序保证
  • HashMap:无排序保证,最佳性能

一般来说,最佳实践是使用Map 作为变量的类型,然后根据代码的需要实例化一个实现类型。 HashMap 通常是首选,除非您需要一些订购保证,在这种情况下,LinkedHashMapTreeMap 是不错的选择。

【讨论】:

  • stevevls,HashMap 在迭代上比 LinkedHashMap 更差,而且速度更快:它是一个基于树的哈希表,在当今的硬件上很烂
  • @bestsss 我很确定HashMap不是基于树的,只有TreeMap 是。
  • @Waldheinz,那么您需要再次检查。我绝对肯定是的。它是一个桶数组,每次碰撞都是一个链表,整个结构是一棵树,尽管不是二元的,而是一棵树的地狱。所以,你不确定。另一个流行的散列选项是线性探测,它非常好于基于树的探测。
  • @bestsss 你是对的,附加到存储桶的列表可能确实会损害局部性。为洞察力 +1。
  • @Waldheinz,是的,还有一些间接需要。第一个桶(Map.Entry)本身可以省略,只使用带有键/值邻居的对象[]。这消除了 put 上的分配并消除了 get 上的间接性。遍历也快得多(它基本上是遍历一个 ArrayList)等等。
【解决方案3】:

所有类都实现了 Map 接口并提供了几乎相同的功能。最重要的区别是条目的迭代顺序:

HashMap 绝对不保证迭代顺序。当添加新元素时,它甚至可以(并且将会)完全改变。 TreeMap 将根据它们的 compareTo() 方法(或外部提供的比较器)根据键的“自然顺序”进行迭代。此外,它还实现了 SortedMap 接口,该接口包含依赖于此排序顺序的方法。 LinkedHashMap 将按照条目放入地图的顺序进行迭代 “哈希表”是基于哈希的映射的通用名称。在 Java API 的上下文中,Hashtable 在集合框架存在之前的 Java 1.1 时代是一个过时的类。不应再使用它,因为它的 API 中充斥着重复功能的过时方法,并且它的方法是同步的(这会降低性能并且通常是无用的)。使用 ConcurrrentHashMap 而不是 Hashtable。

【讨论】:

    猜你喜欢
    • 2011-02-22
    • 2020-10-11
    • 2010-11-15
    • 1970-01-01
    • 2012-02-11
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    相关资源
    最近更新 更多