Java HashSet

2025年4月1日 | 阅读 8 分钟

Java HashSet 类用于创建一个使用哈希表进行存储的集合。它继承了 AbstractSet 类并实现了 Set 接口。

关于 Java HashSet 类的要点如下:

  • HashSet 使用一种称为 **哈希 (hashing)** 的机制来存储元素。
  • HashSet 只包含唯一元素。
  • HashSet 允许 null 值。
  • HashSet 类是非同步的。
  • HashSet 不维护插入顺序。在这里,元素根据它们的哈希码插入。
  • HashSet 是搜索操作的最佳方法。
  • HashSet 的初始默认容量为 16,负载因子为 0.75。

List 和 Set 的区别

List 可以包含重复元素,而 Set 只包含唯一元素。

HashSet 类的继承结构

HashSet 类扩展了 AbstractSet 类,而 AbstractSet 类实现了 Set 接口。Set 接口按照继承关系继承了 Collection 和 Iterable 接口。

Java 中的 HashSet 是一个实现了 Set 接口的集合类,这意味着它存储唯一元素的集合。它不允许重复元素。在内部,HashSet 使用 HashMap 来存储其元素。HashSet 中的每个元素都存储为 HashMap 中的一个键,并关联一个虚拟值。HashSet 使用元素的哈希码来确定其在底层哈希表中的位置,这使得基本的 add、remove 和 contains 操作具有恒定的时间复杂度(O(1)),前提是哈希函数良好。

Java HashSet class hierarchy

HashSet 的一个关键特性是它能够维护一个不包含任何特定顺序的元素集合。这意味着当遍历元素时,添加元素到 HashSet 的顺序不会被保留。如果我们想保留插入顺序,可以使用 LinkedHashSet,它是 Set 接口的另一个实现,它保留了其元素的插入顺序。

HashSet 不允许 null 元素,但它可以包含一个 null 值。如果我们尝试向 HashSet 添加重复元素,add 方法将返回 false,HashSet 将保持不变。HashSet 还提供用于集合操作的方法,如并集、交集和差集。然而,与其他一些集合类不同,HashSet 是不同步的,这意味着它不是线程安全的。如果我们想要一个同步(线程安全)版本的 HashSet,可以使用 Collections.synchronizedSet 方法将我们的 HashSet 包装成一个同步集。

HashSet 类声明

让我们看看 java.util.HashSet 类的声明。

Java HashSet 类的构造函数

序号构造函数描述
1)HashSet()用于构造一个默认的 HashSet。
2)HashSet(int capacity)用于将哈希集的容量初始化为给定的整数值 capacity。随着元素添加到 HashSet 中,容量会自动增长。
3)HashSet(int capacity, float loadFactor)用于将哈希集的容量初始化为给定的整数值 capacity 和指定的负载因子。
4)HashSet(Collection<? extends E> c)用于通过使用集合 c 的元素来初始化哈希集。

Java HashSet 类的方法

序号修饰符 & 类型方法描述
1)booleanadd(E e)用于将指定元素添加到此集合中,如果该元素尚不存在。
2)voidclear()用于从集合中删除所有元素。
3)objectclone()用于返回此 HashSet 实例的浅表副本:元素本身不会被克隆。
4)booleancontains(Object o)用于如果此集合包含指定元素,则返回 true。
5)booleanisEmpty()用于如果此集合不包含任何元素,则返回 true。
6)Iterator<E>iterator()用于返回此集合中元素的迭代器。
7)booleanremove(Object o)用于如果指定元素存在于此集合中,则将其从此集合中移除。
8)intsize()用于返回集合中的元素数量。
9)Spliterator<E>spliterator()用于创建集合中元素的延迟绑定且故障快速(fail-fast)的 Spliterator。

Java HashSet 示例

让我们看一个简单的 HashSet 示例。请注意,元素的迭代顺序是无序的。

HashSetExample1.java

输出

Five
One
Four
Two
Three

忽略重复元素

在这个示例中,我们看到 HashSet 不允许重复元素。

示例

编译并运行

输出

       Ajay
       Vijay
       Ravi

删除元素

在这里,我们看到删除元素的各种方法。

示例

编译并运行

输出

An initial list of elements: [Vijay, Ravi, Arun, Sumit]
After invoking remove(object) method: [Vijay, Arun, Sumit]
Updated List: [Vijay, Arun, Gaurav, Sumit, Ajay]
After invoking removeAll() method: [Vijay, Arun, Sumit]
After invoking removeIf() method: [Arun, Sumit]
After invoking clear() method: []

从另一个集合创建 Java HashSet

HashSetExample4.java

输出

Vijay
Ravi
Gaurav
Ajay

Java HashSet 示例:图书

让我们看一个 HashSet 示例,我们在其中将图书添加到集合中并打印所有图书。

示例

编译并运行

输出

101 Let us C Yashwant Kanetkar BPB 8
102 Data Communications & Networking Forouzan Mc Graw Hill 4
103 Operating System Galvin Wiley 6

使用 Java HashSet 的优点

Java HashSets 提供了几个优点,使其成为某些编程任务的有用选择。一个关键的优点是它能够存储唯一元素,这使其适用于不允许重复元素的应用程序。此功能简化了维护不同值集合的过程,因为 HashSet 会自动处理重复项的检测和删除。

Java HashSets 的另一个优点是它在添加、删除和检查元素是否存在等基本操作方面的高效性能。HashSet 通过使用哈希表来存储其元素来实现这种效率,这使得在平均情况下,这些操作具有恒定的时间复杂度(O(1)),前提是哈希函数良好。

此外,Java HashSets 提供了广泛的集合操作,例如并集、交集和差集,这些在操作元素集合时非常有用。这些操作也执行得很高效,使得 HashSet 成为处理集合操作任务的合适选择。

HashSet 的内部实现也使其适用于需要快速查找时间的场景。由于 HashSet 使用哈希来确定其底层哈希表中元素的位置,因此它可以根据元素的哈希码快速定位元素,从而提供从集合中检索元素的快速访问时间。

总而言之,Java HashSets 结合了效率、简单性和灵活性,使其成为 Java 应用程序中管理唯一元素集合的宝贵工具。

Java HashSet 在 Java 中的缺点

虽然 Java HashSets 提供了许多优点,但它们也有一些重要的缺点需要考虑。一个缺点是 HashSet 不保证其元素的顺序。这意味着当遍历元素时,添加元素到 HashSet 的顺序不会被保留。如果您需要特定的顺序,您可能需要使用不同的数据结构,例如 LinkedHashSet,它会保留其元素的插入顺序。

Java HashSets 的另一个缺点是它们不允许重复元素。虽然这通常是一个理想的特性,但在某些情况下,您可能需要存储同一个元素的多个副本。在这种情况下,HashSet 不适用,您可能需要使用允许重复项的其他数据结构,例如 ArrayList 或 LinkedList。

与某些其他数据结构相比,HashSet 还具有更高的内存开销。这是因为 HashSet 使用哈希表来存储其元素,这需要额外的内存来维护哈希表的结构。如果内存使用量是一个问题,您可能需要考虑使用其他内存开销较低的数据结构。

此外,HashSet 是不同步的,这意味着它不是线程安全的。如果您需要在多线程环境中使用 HashSet,您将需要手动同步对 HashSet 的访问,以避免并发修改问题。这可能会增加代码的复杂性,并可能影响性能。

总而言之,虽然 Java HashSets 提供了许多优点,例如高效的性能和内置的重复项检测,但它们也有一些限制,在为您的应用程序选择合适的数据结构时需要考虑。

让我们通过一个示例程序来理解 Java 中的 Java HashSet。

示例 1

文件名: HashSetExample.java

输出

HashSet: [Apple, Orange, Banana]
Iterating over the HashSet using Iterator: Apple Orange Banana
HashSet converted to array: Apple Orange Banana
HashSet of custom objects: [Person{name='Alice', age=30}, Person{name='Bob', age=25}]

下一个主题Java LinkedHashSet 类