HashMap和Hashtable的区别?

HashMap和a 之间的区别是Hashtable什么?

哪种方法对非线程应用程序更有效?


Java中的HashMap和Hashtable有几个区别:

  1. Hashtable同步的,而HashMap不是。这HashMap对非线程应用程序更好,因为非同步对象通常比同步对象执行得更好。
  2. Hashtable不允许null键或值。 HashMap允许一个null键和任意数量的null值。
  3. 其中一个是HashMap的子类LinkedHashMap,所以如果您希望可预测的迭代顺序(默认情况下是插入顺序),则可以轻松地替换HashMapfor a LinkedHashMap。如果你正在使用这将不那么容易Hashtable

由于同步不是你的问题,我建议HashMap。如果同步成为问题,你也可以看看ConcurrentHashMap

 


请注意,很多答案指出Hashtable是同步的。 在实践中,这种购买很少。 在访问器/增量器方法上的同步将停止两个线程同时添加或从地图中删除,但在现实世界中,您经常需要额外的同步。

一个非常常见的习惯用法是“检查然后放入” – 即在Map中查找一个条目,如果它尚不存在,则添加它。无论您使用Hashtable还是HashMap,这都不是原子操作。

等价的同步HashMap可以通过以下方式获得:

Collections.synchronizedMap(myMap);

但要正确实现此逻辑,您需要对表单进行其他同步

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

即使迭代Hashtable的条目(或由Collections.synchronizedMap获取的HashMap)也不是线程安全的,除非您还通过附加同步防止修改映射。

ConcurrentMap接口的实现(例如ConcurrentHashMap)通过包含线程安全的check-then-act语义来解决其中的一些问题,例如:

ConcurrentMap.putIfAbsent(key, value);

没有人提到的事实,Hashtable不是 Java集合框架的一部分-它只是提供了一个类似的API。此外,Hashtable被视为遗留代码。没有任何关于Hashtable使用HashMap或派生无法完成的事情HashMap,因此对于新代码,我没有看到任何回到的理由Hashtable

在面试中经常会问这个问题,以检查考生是否理解收集班的正确使用方式,并了解可用的替代解决方案。

  1. HashMap类大致等同于Hashtable,不同之处在于它不同步并允许使用空值。(HashMap允许空值作为键和值,而Hashtable不允许空值)。
  2. HashMap不能保证地图的顺序会随着时间的推移保持不变。
  3. HashMap是非同步的,而Hashtable是同步的。
  4. HashMap中的迭代器在Hashtable的枚举器不可用时为fail-safe,如果其他任何线程通过添加或除去Iterator自身的remove()方法之外的任何元素来在结构上修改映射,则会抛出ConcurrentModificationException。但这不是一个有保证的行为,并且将由JVM尽最大努力完成。

关于一些重要术语的注释

  1. 同步意味着只有一个线程可以在一个时间点修改哈希表。基本上,这意味着任何线程在执行哈希表更新之前都必须获取对象上的锁,而其他人将等待锁释放。
  2. 故障安全与迭代器的上下文相关。如果在集合对象上创建了迭代器,并且某个其他线程试图“在结构上”修改集合对象,则会引发并发修改异常。尽管其他线程可以调用“set”方法,因为它不会在“结构上”修改集合。但是,如果在调用“set”之前,集合已经在结构上进行了修改,则会抛出“IllegalArgumentException”。
  3. 结构修改意味着删除或插入可有效改变地图结构的元素。

HashMap可以被同步

Map m = Collections.synchronizeMap(hashMap);

Map提供Collection视图,而不是直接支持通过Enumeration对象进行迭代。集合视图大大增强了界面的表现力,这将在本节后面讨论。Map允许你遍历键,值或键值对; 哈希表不提供第三种选择。Map提供了一种安全的方法来在迭代过程中删除条目; 哈希表没有。最后,Map修复了Hashtable接口中的一个小缺陷。Hashtable有一个名为contains的方法,如果Hashtable包含给定的值,则返回true。考虑到它的名称,如果Hashtable包含给定的键,那么您会希望此方法返回true,因为该键是Hashtable的主要访问机制。通过重命名方法containsValue,Map接口消除了混淆的根源。也,


请记住,这HashTable是在Java集合框架(JCF​​)推出之前的遗留类,并且稍后进行了改进以实现Map接口。所以是VectorStack

因此,在其他人指出的JCF中总是有更好的替代方案,因此请始终远离新代码

这里是你会发现有用的Java集合备忘单。注意灰色块包含遗留类HashTable,Vector和Stack。

 


HashMapMap使用哈希码来索引数组的接口的实现。 Hashtable:你好,1998年打电话。他们希望他们的收集API回来。

不过,尽管如此,你最好远离Hashtable一切。对于单线程应用程序,您不需要额外的同步开销。对于高度并发的应用程序,偏执同步可能会导致饥饿,死锁或不必要的垃圾收集暂停。像Tim Howland指出的那样,你可以ConcurrentHashMap改用。

添加评论

友情链接:蝴蝶教程