我正在学习Java集合框架,并获得了适度的理解。现在,当我更深入一点的时候,我对< code>HashMap,< code>HashSet,< code>Hashtable有些怀疑。
< code>HashMap的Javadoc说:
Map接口的基于哈希表的实现。此实现提供所有可选的映射操作,并允许空值和空键。
HashSet
的Javadoc说:
此类实现了Set接口,该接口由哈希表(实际上是HashMap实例)支持。它不保证集合的迭代顺序;特别是,它不能保证订单随时间保持不变。
Hashtable
的 Javadoc 说:
此类实现了一个哈希表,它将键映射到值。任何非空对象都可以用作键或值。
令人困惑的是,它们都实现了哈希表
。他们实现了哈希表的概念吗?
似乎所有这些都是相互关联的,但我无法完全理解它。
有人能用简单的语言帮助我理解这个概念吗。
Java的Set
和Map
接口指定了两种截然不同的集合类型。一个Set
就是它听起来的样子:一组不同的(不相等的)对象,没有其他结构。一个Map
在概念上也是它听起来的样子:从一组对象(不同的键)到一组对象(值)的映射。Hashtable
和HashMap
都实现了Map
,HashSet
实现了Set
,它们都对集合中包含的键/对象使用哈希码来提高性能。
哈希表
和HashMap
Hashtable
是一个遗留类,几乎总是应该避免使用HashMap
。它们基本上执行相同的操作,只是 Hashtable
中的大多数方法都是同步的,这使得单个方法调用是线程安全的。1 如果您使用多个线程和 HashMap
,则必须提供自己的同步或其他线程安全机制。
Hashtable
的问题在于同步每个方法调用(这是一个并非微不足道的操作)通常是错误的事情。要么根本不需要同步,要么从应用程序逻辑的角度来看,需要通过跨多个方法调用的事务进行同步。由于不可能在不破坏现有代码的情况下简单地从 Hashtable
中删除方法级同步,因此 Collections 框架作者需要提出一个新类;因此哈希图
。这也是一个更好的名字,因为很明显它是一种地图
。
哦,如果你确实需要方法级同步,你还是不应该使用< code>Hashtable。相反,您可以调用< code > collections . synchronized map()将任何地图转换为同步地图。或者,您可以使用< code>ConcurrentHashMap,根据文档,它“遵循与< code>Hashtable相同的功能规范”,但是具有更好的性能和附加功能(例如< code>putIfAbsent())。
< sup>1 还有其他差异(在我看来不太重要),例如< code>HashMap支持< code>null值和键。
HashSet
在功能方面,HashSet
与HashMap
无关。它恰好在内部使用HashMap
来实现Set
功能。出于某种原因,集合框架开发人员认为将这种内部实现细节作为类的公共规范的一部分是个好主意。(在我看来,这是一个错误。)
Hashtable 是一个在 Java 有泛型之前创建的旧类。它只是为了向后兼容。请改用哈希图。
当您不需要将键映射到值时,请使用哈希集。它建立在与哈希表相同的算法之上,但它用于根本不同的目的。
HashMap和HashTable都继承了Map接口,具有几乎相同的工作和属性。但主要区别如下
1.Hashmap是键和值对的无序映射。我们可以在hashmap中包含空的键或值对。同样,hashmap是不同步的(也就是说,不是线程安全的,多个线程可以同时访问和修改它。)但是我们可以从外部使hashmap线程安全。所以如果我们不考虑同步问题,那么hashmap是更好的选择。
2. HashTable:-同步的hashMap(即线程安全的hashmap)。但在这种情况下,键和值对永远不会为空。在Hashtable中,我们指定一个用作键的对象,以及我们想要与该键关联的值。然后对键进行散列,生成的哈希码用作值存储在表中的索引
3.HashSet:-HashSet继承了Set接口,并且最终也基于hashtable(或者我们可以说只深度连接到我们的hashmap ),但是在这种情况下,键和值对总是唯一的,不允许有重复的值。根据对象的哈希代码插入对象。
总而言之,我们可以说所有三个集合都已连接到 Map 接口。