Java集合框架中的Hashtable、HashMap、HashSet、哈希表概念

Posted

技术标签:

【中文标题】Java集合框架中的Hashtable、HashMap、HashSet、哈希表概念【英文标题】:Hashtable, HashMap, HashSet , hash table concept in Java collection framework 【发布时间】:2018-05-30 01:08:17 【问题描述】:

我正在学习 Java 集合框架并获得了适度的理解。现在,当我走得更远时,我对:HashMapHashSetHashtable 产生了一些疑问。

HashMap 的 Javadoc 说:

Map 接口的基于哈希表的实现。这 实现提供了所有可选的映射操作,并且 允许空值和空键。

HashSet 的 Javadoc 说:

这个类实现了 Set 接口,由一个哈希表支持 (实际上是一个 HashMap 实例)。它不保证 集合的迭代顺序;特别是,它不保证 随着时间的推移,顺序将保持不变。

Hashtable 的 Javadoc 说:

这个类实现了一个哈希表,它将键映射到值。任何 非空对象可以用作键或值。

令人困惑的是它们都实现了hash table。他们是否实现了哈希表概念

似乎所有这些都是相互关联的,但我无法完全理解。

谁能帮我用简单的语言理解这个概念。

【问题讨论】:

【参考方案1】:

Hashtable 是一个在 Java 有泛型之前创建的旧类。它只是为了向后兼容而存在。请改用 HashMap。

当您不需要将键映射到值时,请使用 HashSet。它建立在与哈希表相同的算法上,但用于根本不同的目的。

【讨论】:

@EJP:你能帮我理解更多吗?您对我之前问题的回答(是的,我确实记得)有助于理清思路。 @EJP : 尽管这些类的目的不同,但在内部所有这些都实现了“哈希表”的概念是否正确? 自引入泛型以来,Hashtable 也成为了泛型类。【参考方案2】:

Java 的SetMap 接口指定了两种截然不同的集合类型。 Set 就是它听起来的样子:不同(不相等)对象的集合,没有其他结构。从概念上讲,Map 也就是它听起来的样子:从一组对象(不同的键)到一组对象(值)的映射。 HashtableHashMap 都实现了MapHashSet 实现了Set,并且它们都对集合中包含的键/对象使用哈希码来提高性能。

HashtableHashMap

Hashtable 是一个遗留类,几乎总是应该避免使用HashMap。它们基本上做同样的事情,除了Hashtable 中的大多数方法都是同步的,这使得各个方法调用线程安全。1 如果您使用多个同步,则必须提供自己的同步或其他线程安全机制线程和HashMap

Hashtable 的问题在于同步每个方法调用(这是一个不重要的操作)通常是错误的。要么您根本不需要同步,要么从应用程序逻辑的角度来看,您需要对跨越多个方法调用的事务进行同步。由于不可能在不破坏现有代码的情况下简单地从 Hashtable 中删除方法级同步,因此 Collections 框架的作者需要提出一个新类;因此HashMap。这也是一个更好的名字,因为很明显它是一种Map

哦,如果你确实需要方法级同步,你仍然不应该使用Hashtable。相反,您可以致电Collections.synchronizedMap() 将任何地图转换为同步地图。或者,您可以使用ConcurrentHashMap,根据the docs:“遵循与Hashtable 相同的功能规范”,但具有更好的性能和附加功能(例如putIfAbsent())。

1还有其他差异(在我看来不太重要),例如 HashMap 支持 null 值和键。

HashSet

在功能方面,HashSetHashMap 无关。它恰好在内部使用HashMap 来实现Set 功能。出于某种原因,Collections 框架开发人员认为将这个内部实现细节作为类的公共规范的一部分是一个好主意。 (在我看来,这是一个错误。)

【讨论】:

这是解决我困惑的最有见地的答案之一。谢谢特德霍普!我当时想,为什么 Hashtable 不是驼峰式和同步...,而是 HashMap/HashSet 驼峰式和同步;你的回答解释了它。【参考方案3】:

HashMap 和 HashTable 都继承了 Map 接口,工作和属性几乎相同,但主要区别如下:-

1.Hashmap是键值对的无序映射。我们可以在hashmap中包含空键或值对。hashmap也是不同步的(即不是线程安全的,多个线程可以同时访问和修改它时间。)但是我们可以在外部使 hashmap 成为线程安全的。所以如果我们不考虑同步问题,那么 hashmap 是更可取的。

2.HashTable:- 一个同步的hashMap(即线程安全的hashmap)。但是在这种情况下,键和值对永远不会为空。在Hashtable中,我们指定一个用作键的对象,而值我们想关联到那个键。然后对键进行哈希处理,生成的哈希码用作值在表中存储的索引

3.HashSet:-一个hashset继承了set接口,最后它也基于hashtable(或者我们可以说只与我们的hashmap深度连接)但是在这种情况下键和值对总是唯一的,不允许重复值.但是允许空键值。对象是根据它们的哈希码插入的。

总而言之,我们可以说所有三个集合都已连接到地图接口。

【讨论】:

【参考方案4】:

Hashtable 是同步的,但 HashMap 不是,但是您可以借助方法 Collections.synchronizedMap() 使 HashMap 同步。 Hashtable、HashMap 和 HashSet 都是基于 Hash Table 数据结构的。您可以为 HashMap 使用一个空键以及您想要哪种空值,但 Hashtable 不允许空键或空值。基本上在 HashSet 下工作的是 HashMap ,其中 value 是 Object 因此 HashSet 值是唯一的,因为 HashMap 键是唯一的。因此,要将键值对放入 Hashmap 或 Hashtable 或将元素放入 HashSet,您需要从 Object 类中覆盖 hashcode 和 equals 方法以纠正此实现的工作。这是因为在这个实现下是工作哈希表算法和哈希码,需要equals才能将值放入正确的桶中。重要的是要知道您需要将 String 或任何其他包装类(例如 Integer)用作键,这是因为此对象是不可变的,它们可以是此实现的好键,或者您可以创建自己的不可变类并将其用作键.使用不可变对象作为键是一种很好的做法,因为创建后它们无法更改其状态,因此哈希码始终相同。

【讨论】:

以上是关于Java集合框架中的Hashtable、HashMap、HashSet、哈希表概念的主要内容,如果未能解决你的问题,请参考以下文章

深入理解java集合框架之---------HashTable集合

Java集合框架中的Hashtable,HashMap,HashSet,哈希表概念

Java中的集合框架-Map

JAVA-初步认识-常用对象API(集合框架-Map集合常见子类对象)

Map...---HashMap和Hashtable的区别-----...LinkedHashMap

Java面试准备之集合框架