HashSet概述
HashSet是Java集合框架中的一个重要类,实现了Set接口。它内部使用哈希表(实际上是HashMap实例)来存储元素。HashSet不保证元素的迭代顺序,这意味着每次迭代的结果可能不同。此外,HashSet是非线程安全的,如果需要线程安全的Set,可以使用Collections.synchronizedSet方法进行包装:
Set s = Collections.synchronizedSet(new HashSet(...));
HashSet的特点
1. HashSet不维护任何顺序,元素将以随机顺序返回。
2. HashSet不允许有重复元素,如果尝试添加重复元素,添加操作将被忽略。
3. HashSet允许有一个null值,但多次插入null值只会保留一个。
4. HashSet是非线程安全的。
5. HashSet返回的迭代器是快速失败的,即在创建迭代器后修改HashSet会导致迭代器抛出ConcurrentModificationException异常,除非通过迭代器的remove方法进行修改。
HashSet的常用操作
1. 基本示例
package com.example.collection;
import java.util.HashSet;
public class HashSetExample {
public static void main(String[] args) {
// 创建HashSet
HashSet hset = new HashSet<>();
// 添加元素
hset.add("Apple");
hset.add("Mango");
hset.add("Grapes");
hset.add("Orange");
hset.add("Fig");
// 尝试添加重复元素
hset.add("Apple");
hset.add("Mango");
// 尝试添加null值
hset.add(null);
hset.add(null);
// 显示HashSet元素
System.out.println(hset);
}
}
输出:
[null, Apple, Grapes, Fig, Mango, Orange]
2. 删除所有元素
package com.example.collection;
import java.util.HashSet;
public class EmptyHashSetExample {
public static void main(String[] args) {
// 创建HashSet
HashSet hset = new HashSet<>();
// 添加元素
hset.add("Element1");
hset.add("Element2");
hset.add("Element3");
hset.add("Element4");
hset.add("Element5");
// 显示HashSet元素
System.out.println("Before: HashSet contains: " + hset);
// 清空HashSet
hset.clear();
// 再次显示HashSet元素
System.out.println("After: HashSet contains: " + hset);
}
}
输出:
Before: HashSet contains: [Element5, Element4, Element3, Element2, Element1]
After: HashSet contains: []
3. 迭代元素
3.1 使用Iterator
3.2 使用for-each循环
package com.example.collection;
import java.util.HashSet;
import java.util.Iterator;
public class IterateHashSet {
public static void main(String[] args) {
// 创建HashSet
HashSet hset = new HashSet<>();
// 添加元素
hset.add("Chaitanya");
hset.add("Rahul");
hset.add("Tim");
hset.add("Rick");
hset.add("Harry");
// 使用Iterator迭代
System.out.println("----使用Iterator:");
Iterator it = hset.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
// 使用for-each循环迭代
System.out.println("----使用for-each循环:");
for (String temp : hset) {
System.out.println(temp);
}
}
}
输出:
----使用Iterator:
Chaitanya
Rahul
Harry
Tim
Rick
----使用for-each循环:
Chaitanya
Rahul
Harry
Tim
Rick
4. 转换为数组
package com.example.collection;
import java.util.HashSet;
public class ConvertHashSetToArray {
public static void main(String[] args) {
// 创建HashSet
HashSet hset = new HashSet<>();
// 添加元素
hset.add("Element1");
hset.add("Element2");
hset.add("Element3");
hset.add("Element4");
// 显示HashSet元素
System.out.println("HashSet contains: " + hset);
// 转换为数组
String[] array = new String[hset.size()];
hset.toArray(array);
// 显示数组元素
System.out.println("Array elements:");
for (String temp : array) {
System.out.println(temp);
}
}
}
输出:
HashSet contains: [Element4, Element3, Element2, Element1]
Array elements:
Element4
Element3
Element2
Element1
5. 转换为TreeSet
package com.example.collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class ConvertHashSetToTreeSet {
public static void main(String[] args) {
// 创建HashSet
HashSet hset = new HashSet<>();
// 添加元素
hset.add("Element1");
hset.add("Element2");
hset.add("Element3");
hset.add("Element4");
// 显示HashSet元素
System.out.println("HashSet contains: " + hset);
// 转换为TreeSet
Set tset = new TreeSet<>(hset);
// 显示TreeSet元素
System.out.println("TreeSet contains:");
for (String temp : tset) {
System.out.println(temp);
}
}
}
输出:
HashSet contains: [Element4, Element3, Element2, Element1]
TreeSet contains:
Element1
Element2
Element3
Element4
6. 转换为List/ArrayList
package com.example.collection;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class ConvertHashSetToList {
public static void main(String[] args) {
// 创建HashSet
HashSet hset = new HashSet<>();
// 添加元素
hset.add("Steve");
hset.add("Matt");
hset.add("Govinda");
hset.add("John");
hset.add("Tommy");
// 显示HashSet元素
System.out.println("HashSet contains: " + hset);
// 转换为ArrayList
List list = new ArrayList<>(hset);
// 显示ArrayList元素
System.out.println("ArrayList contains: " + list);
}
}
输出:
HashSet contains: [Matt, Steve, Govinda, John, Tommy]
ArrayList contains: [Matt, Steve, Govinda, John, Tommy]
HashSet与HashMap的比较
相同点
1. 两者都是非线程安全的。
2. 都不保证元素的顺序。
3. 从源码角度来看,HashSet内部使用HashMap来实现其操作。
4. 在添加、删除元素等操作时,两者的性能表现一致。
不同点
HashSet | HashMap |
实现的是Set接口 | 实现的是Map接口 |
存储的是单个对象(元素或值),例如:[null, Apple, Grapes, Fig, Mango, Orange] | 存储的是键值对(Key-Value) |
不允许有重复值 | 不允许有重复键,但可以有多个重复值 |
只允许有一个null元素 | 允许有一个null键,多个null值 |