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年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》