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);
- }
- }
- }