HashSet<E>
HashSet<E> 是 Java 集合框架中的一个重要类,它实现了 Set<E> 接口,用于存储不重复元素的集合。下面从多个方面详细介绍 HashSet<E> 类。
1. 类定义与继承关系
HashSet<E> 类的定义如下:
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
它继承自 AbstractSet<E> 抽象类,实现了 Set<E>、Cloneable 和 java.io.Serializable 接口。这表明 HashSet 具备集合的基本特性,支持克隆操作,并且可以进行序列化。
2. 底层实现原理
HashSet 底层基于 HashMap 实现。在 HashSet 中,元素被存储为 HashMap 的键,而 HashMap 的值则统一使用一个静态的 PRESENT 对象。通过 HashMap 的哈希表结构,HashSet 能够快速地判断元素是否重复。
3. 主要特性
- 无序性:
HashSet不保证元素的存储顺序,即元素插入的顺序和遍历的顺序可能不同。 - 唯一性:
HashSet不允许存储重复的元素。当添加重复元素时,添加操作会失败。判断元素是否重复是通过元素的hashCode()和equals()方法来实现的。 - 允许
null元素:HashSet允许存储一个null元素。
4. 常用构造方法
HashSet():创建一个空的HashSet,初始容量为 16,负载因子为 0.75。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
}
}
HashSet(Collection<? extends E> c):创建一个包含指定集合中所有元素的HashSet。
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class HashSetExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
HashSet<String> set = new HashSet<>(list);
}
}
HashSet(int initialCapacity):创建一个具有指定初始容量的空HashSet,负载因子为 0.75。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>(20);
}
}
HashSet(int initialCapacity, float loadFactor):创建一个具有指定初始容量和负载因子的空HashSet。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>(20, 0.8f);
}
}
5. 常用方法
boolean add(E e):如果指定元素不存在于集合中,则将其添加到集合中,添加成功返回true,否则返回false。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
boolean result = set.add("apple");
System.out.println(result); // 输出 true
result = set.add("apple");
System.out.println(result); // 输出 false
}
}
boolean remove(Object o):如果集合中存在指定元素,则将其移除,移除成功返回true,否则返回false。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
boolean result = set.remove("apple");
System.out.println(result); // 输出 true
}
}
boolean contains(Object o):判断集合中是否包含指定元素,包含返回true,否则返回false。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
boolean result = set.contains("apple");
System.out.println(result); // 输出 true
}
}
int size():返回集合中元素的数量。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
int size = set.size();
System.out.println(size); // 输出 2
}
}
void clear():移除集合中的所有元素。
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
set.clear();
System.out.println(set.size()); // 输出 0
}
}
6. 遍历方式
- 迭代器(Iterator):
import java.util.HashSet;
import java.util.Iterator;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
}
}
- 增强 for 循环:
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
for (String element : set) {
System.out.println(element);
}
}
}
- Java 8 的
forEach方法结合 Lambda 表达式:
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.forEach(element -> System.out.println(element));
}
}
7. 性能分析
- 插入和查找操作:
HashSet的插入和查找操作的平均时间复杂度为,因为它基于哈希表实现。但在最坏情况下(哈希冲突严重),时间复杂度会退化为
。
- 空间复杂度:
HashSet的空间复杂度为,其中
是集合中元素的数量。
8. 注意事项
- 元素的
hashCode()和equals()方法:为了确保HashSet能够正确判断元素是否重复,存储在HashSet中的元素必须正确重写hashCode()和equals()方法。 - 线程安全:
HashSet不是线程安全的。如果需要在多线程环境下使用,可以使用Collections.synchronizedSet()方法将其转换为线程安全的集合,或者使用ConcurrentHashMap实现的ConcurrentSkipListSet。
综上所述,HashSet 是一个非常实用的集合类,适用于需要存储不重复元素且对插入和查找性能有较高要求的场景。
Java集合框架 文章被收录于专栏
Java集合框架是Java提供的一组用于存储和操作数据的类和接口,它位于java.util包中,为开发者提供了强大且灵活的数据存储和处理能力。以下将从整体架构、主要接口、常用实现类、使用场景以及示例代码等方面详细介绍Java集合框架。

查看22道真题和解析