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集合框架。