Java中的HashMap和Hashtable有什么区别?

问题描述:

Java 中的 HashMap 和 Hashtable 有什么区别?

哪个对非线程应用程序更有效?

解决方案1:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

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

Hashtable 是同步的,而 HashMap 不是。这使得 HashMap 更适合非线程应用程序,因为非同步对象通常比同步对象执行得更好。 Hashtable 不允许空键或空值。 HashMap 允许一个空键和任意数量的空值。 HashMap 的子类之一是 LinkedHashMap,因此如果您想要可预测的迭代顺序(默认为插入顺序),您可以轻松地将 HashMap 换成 LinkedHashMap。如果您使用 Hashtable,这将不会那么容易。

由于同步对您来说不是问题,因此我建议您使用 HashMap。如果同步成为问题,您还可以查看 ConcurrentHashMap。

如果要使 HashMap 线程安全,请使用 Collections.synchronizedMap()。

我还要评论说,Hashtable 中对线程安全的幼稚方法(“同步每个方法应该解决任何并发问题!”)使得线程应用程序非常更糟糕。您最好在外部同步 HashMap(并考虑后果),或使用 ConcurrentMap 实现(并利用其扩展 API 实现并发)。底线:使用 Hashtable 的唯一原因是旧版 API(约 1996 年)需要它时。

HashMap 为程序员在实际使用时编写线程安全代码提供了灵活性。我很少需要像 ConcurrentHashMap 或 HashTable 这样的线程安全集合。我需要的是同步块中的某些函数集或某些语句是线程安全的。

Hashtable 已过时,我们将 HashMap 用于非线程安全环境。如果您需要线程安全,则可以使用 Collections.synchronizedMap() 或使用比哈希表更有效的 ConcurrentHashMap。

它已经过时但没有被弃用,我想知道为什么会这样。我猜想删除这个类(和 Vector 出于同样的原因)会破坏太多现有的代码,并且使用 @Deprecated 进行注释将意味着删除代码的意图,这显然不存在。

解决方案2:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

请注意,许多答案都表明 Hashtable 是同步的。在实践中,这给你带来的收益很少。访问器/修改器方法上的同步将停止两个线程同时从映射中添加或删除,但在现实世界中,您通常需要额外的同步。

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

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

Collections.synchronizedMap(myMap);

但是要正确实现此逻辑,您需要对表单进行额外的同步:

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

即使遍历 Hashtable 的条目(或 Collections.synchronizedMap 获得的 HashMap)也不是线程安全的,除非您还保护 Map 不通过额外的同步被修改。

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

ConcurrentMap.putIfAbsent(key, value);

另请注意,如果修改了 HashMap,则指向它的迭代器将变为无效。

那么 synchronized(myMap) {...} 和 ConcurrentHashMap 在线程安全方面有什么区别吗?

在 JVM 开发团队中工作多年,我可以说 Hashtable 的内部同步至少对于在客户编写狡猾的并发代码时正确地指出客户的代码很有用。当原因是并发修改时,我们收到了一些关于 HashMap 内部失败的投诉(因此“显然”是一个 JDK/JVM 错误)。

Collections.synchronizedMap 的实现包括一个同步的 putIfAbsent,所以你不需要自己使用 containsKey/put。

解决方案3:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

Hashtable 被视为遗留代码。 Hashtable 没有什么是不能使用 HashMap 或 HashMap 派生的,所以对于新代码,我看不出有任何理由回到 Hashtable。

来自 Hashtable javadoc(已添加重点):“从 Java 2 平台 v1.2 开始,该类被改进为实现 Map 接口,使其成为 Java 集合框架的成员。”但是,您是对的,它是遗留代码。使用 Collections.synchronizedMap(HashMap) 可以更有效地获得同步的所有好处。 (类似于 Vector 是 Collections.synchronizedList(ArrayList) 的旧版本。)

@aberrant80:不幸的是,您在这两者之间别无选择,并且在为 J2ME 编程时必须使用 Hashtable ......

同意“哈希表被视为遗留代码”。如果你需要并发,你应该使用 ConcurentHashMap。

解决方案4:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

这个问题经常在面试中被问到,以检查候选人是否理解集合类的正确用法以及是否知道可用的替代解决方案。

HashMap 类与 Hashtable 大致等价,不同之处在于它是非同步的并且允许空值。 (HashMap 允许空值作为键和值,而 Hashtable 不允许空值)。 HashMap 不保证地图的顺序会随着时间的推移保持不变。 HashMap 是非同步的,而 Hashtable 是同步的。 HashMap 中的迭代器是故障安全的,而 Hashtable 的枚举器则不是,如果任何其他线程通过添加或删除除 Iterator 自己的 remove() 方法之外的任何元素在结构上修改映射,则抛出 ConcurrentModificationException。但这不是保证行为,JVM 会尽最大努力来完成。

一些重要术语的注意事项:

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

HashMap 可以通过

Map m = Collections.synchronizeMap(hashMap);

Map 提供 Collection 视图,而不是通过 Enumeration 对象直接支持迭代。集合视图极大地增强了界面的表现力,这将在本节后面讨论。 Map 允许您迭代键、值或键值对; Hashtable 不提供第三个选项。 Map 提供了一种在迭代过程中删除条目的安全方法; Hashtable 没有。最后,Map 修复了 Hashtable 界面中的一个小缺陷。 Hashtable 有一个名为 contains 的方法,如果 Hashtable 包含给定值,则该方法返回 true。鉴于其名称,如果 Hashtable 包含给定键,您会期望此方法返回 true,因为该键是 Hashtable 的主要访问机制。 Map 接口通过重命名方法 containsValue 消除了这种混淆来源。此外,这提高了界面的一致性 - containsValue 与 containsKey 平行。

地图界面

1) HashMap 的迭代器不是故障安全的。他们是快速失败的。这两个术语之间的含义存在巨大差异。 2) HashMap 上没有 set 操作。 3) 如果之前有更改,put(...) 操作不会抛出 IllegalArgumentException。 4) 如果您更改映射,HashMap also 的快速失败行为会发生。 5) 保证快速失败的行为是。 (如果您进行并发修改,则不能保证 HashTable 的行为。实际行为是......不可预测的。)

6) Hashtable 也不保证地图元素的顺序会随着时间的推移保持稳定。 (您可能将 Hashtable 与 LinkedHashMap 混淆了。)

还有其他人真的担心这些天的学生会错误地认为获得集合的“同步版本”意味着您不必在外部同步复合操作吗?我最喜欢的例子是 thing.set(thing.get() + 1);,它经常让新手感到惊讶,因为它完全不受保护,特别是如果 get() 和 set() 是同步方法。他们中的许多人都在期待魔法。

Re 4:ConcurrentModificationException 与线程无关。这是关于保留一个迭代器并修改可能在同一个线程中发生的原始集合。

解决方案5:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

HashMap:Map 接口的实现,它使用哈希码来索引数组。 Hashtable:嗨,1998 年打来的电话。他们希望他们的收藏 API 回来。

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

这实际上是有道理的。 ConcurrentHashMaps 为您提供同步的自由,并且调试更容易。

解决方案6:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

请记住,在引入 Java 集合框架 (JCF) 之前,HashTable 是遗留类,后来经过改进以实现 Map 接口。 Vector 和 Stack 也是如此。

因此,在新代码中始终远离它们,因为正如其他人所指出的那样,JCF 中总是有更好的选择。

这是您会发现有用的 Java collection cheat sheet。请注意,灰色块包含遗留类 HashTable、Vector 和 Stack。

https://i.stack.imgur.com/PyflH.png

解决方案7:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

已经发布了许多好的答案。我正在添加一些新观点并对其进行总结。

HashMap 和 Hashtable 都用于以键值形式存储数据。两者都使用散列技术来存储唯一键。但是下面给出的 HashMap 和 Hashtable 类之间存在许多差异。

哈希映射

HashMap 是非同步的。它不是线程安全的,如果没有适当的同步代码,就不能在多个线程之间共享。 HashMap 允许一个空键和多个空值。 HashMap 是 JDK 1.2 中引入的一个新类。 HashMap 很快。我们可以通过调用此代码 Map m = Collections.synchronizedMap(HashMap); 使 HashMap 同步。 HashMap被Iterator遍历。 HashMap 中的迭代器是快速失败的。 HashMap 继承 AbstractMap 类。

哈希表

哈希表是同步的。它是线程安全的,可以与许多线程共享。 Hashtable 不允许空键或值。 Hashtable 是一个遗留类。哈希表很慢。 Hashtable 是内部同步的,不能不同步。 Hashtable 由 Enumerator 和 Iterator 遍历。 Hashtable 中的枚举器不是快速失败的。 Hashtable 继承 Dictionary 类。

进一步阅读What is difference between HashMap and Hashtable in Java?

https://i.stack.imgur.com/sDoih.png

为什么说~“Hashtable 是一个遗留类”?这方面的支持文件在哪里。

维护 HashMap 比 TreeMap 成本高。因为 HashMap 创建了不必要的额外存储桶。

LinkedHashMap 具有条目的双向链接列表,而不是存储桶。存储桶可通过数组索引访问,无需链接。

Pereira 等人 2016 年的一项研究。发现 Hashtable 对于大多数方法都比 HashMap 快,尤其是对于 containsKey、get、put 和 remove (arXiv:1602.00984)。因此,您声称“HashMap 很快”和“Hastable 很慢”很可能是错误的。

解决方案8:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

看看这张图表。它提供了不同数据结构以及 HashMap 和 Hashtable 之间的比较。比较准确、清晰且易于理解。

Java Collection Matrix

解决方案9:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

除了 izb 所说的,HashMap 允许空值,而 Hashtable 不允许。

另请注意,Hashtable 扩展了 Dictionary 类,作为 Javadocs 状态,已过时并已被 Map 接口取代。

解决方案10:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

Hashtable 与 HashMap 类似,并且具有类似的界面。建议您使用 HashMap,除非您需要支持旧版应用程序或需要同步,因为 Hashtables 方法已同步。因此,在您的情况下,由于您不是多线程,HashMaps 是您最好的选择。

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

解决方案11:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

Hashtable 是同步的,而 HashMap 不是。这使得 Hashtable 比 Hashmap 慢。

对于单线程应用程序,请使用 HashMap,因为它们在功能方面是相同的。

原文链接:https://www.huntsbot.com/qa/eRyy/what-are-the-differences-between-a-hashmap-and-a-hashtable-in-java?lang=zh_CN

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值