
HashSet定义
HashSet是Set接口的一个实现类,其实现类除HashSet之外,还有TreeSet,并继承了Collection,下面是结构图:

public class HashSet
extends AbstractSet
implements Set, Cloneable, java.io.Serializable
{}
HashSet是Java集合框架最常用实现类,是其Set经典实现。
HashSet特点
HashSet有一些典型的特征,大致分为如下6点:
- HashSet底层是包装了一个HashMap实现的;
- 底层数据结构是数组 链表 红黑树;
- HashSet不保证顺序,且非线程安全的;
- HashSet实现了Set Interface,所以不允许重复值;
- 在HashSet中插入的对象不保证以相同顺序插入;
- HashSet中允许使用NULL元素;
HashSet实现原理
对于HashSet而言,它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,如下源码:
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
/**
* Constructs a new, empty set; the backing HashMap instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
// 使用 HashMap 的实例来存储
return map.put(e, PRESENT)==null;
}

在JDK 8版本中,对于哈希表的实现做了一些改进,通过数组 链表 红黑树实现。
当某个桶经常发生哈希冲突时,该链表长度将会变的非常长,下一次新对象将必须依次比较该桶中的所有对象,耗费大量时间降低性能。
为此当桶中对象数量超过8个时,在JDK 8 中会将该链表转换为红黑树(如上图黑色桶所示)进行存储。此举将大大减少新对象在该桶的比较次数,提高性能。
HashSet使用示例
1.添加元素
HashSet新增元素时,如果元素已经存在,它就不会再新增。
示例如下:
import java.util.HashSet;
public class HashSetIntro {
public static void main(String[] args) {
//声明字符串链表
HashSet lang = new HashSet<>();
//新增元素
lang.add("中文");
lang.add("英文");
lang.add("法文");
//存在元素不再新增
lang.add("法文");
System.out.println(lang);
}
}
2.删除元素
import java.util.HashSet;
public class HashSetIntro {
public static void main(String[] args) {
//声明字符串链表
HashSet lang = new HashSet<>();
//新增元素
lang.add("中文");
lang.add("英文");
//删除单个元素
lang.remove("英文");
System.out.println(lang);
}
}
3.访问元素
import java.util.HashSet;
public class RunoobTest {
public static void main(String[] args) {
HashSet sites = new HashSet();
sites.add("taobao");
sites.add("mikechen");
sites.add("baidu");
sites.add("mikechen"); // 重复的元素不会被添加
for (String i : sites) {
System.out.println(i);
}
}
}
mikechen睿哥
10年+一线大厂架构实战经验,就职于阿里、百度等一线大厂,操盘多个亿级大厂核心项目。