java集合框架Set子接口之HashSet源码剖析

简介: HashSet类实现了由哈希表(实际上是HashMap实例)支持的Set接口 , 底层采用HashMap来保存的数据 , 存在HashSet中的元素是无序且不重复的并且HashSet是线程不安全的 , 这种不重复其实是由HashMap实现的 , 所以HashSet的实现也是相对比较简单的 , 对于它的操作其实都是调用HashMap的方法来实现的

HashSet

HashSet类实现了由哈希表(实际上是HashMap实例)支持的Set接口 , 底层采用HashMap来保存的数据 , 存在HashSet中的元素是无序且不重复的并且HashSet是线程不安全的 , 这种不重复其实是由HashMap实现的 , 所以HashSet的实现也是相对比较简单的 , 对于它的操作其实都是调用HashMap的方法来实现的


HashSet类结构图

39e63c8e94ea7089887d527f04c4c0e6_9b0ca548465b43150ee3106752399bdc.png


HashSet基本属性

// 保存数据的容器
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
// 存储在HashMap中的key对应的value值
private static final Object PRESENT = new Object();

HashSet构造方法

loadFactor: 负载因子 , 用来计算HashMap扩容时的阈值


initialCapacity : HashMap的容量


HashMap的阈值计算公式 : 阈值(threshold) = 扩容因子(loadFactor) * 容量(capacity)


如果扩容因子和容量都是默认的话 , 那么阈值就是 0.75f * 16 = 12


如果当HaspMap中table(也称为桶)的长度大于等于阈值时就会触发扩容机制


 

    // HashSet默认无参构造方法 , 直接初始化一个Map
    public HashSet() {
        map = new HashMap<>();
    }
    // 使用默认负载因子计算出HashMap的初始容量 , 并且和16取最大值 , 然后将传入的集合添加到HashSet的构造器
    public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }
    // 使用指定的容量和负载因子进行HashMap的初始化
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }
    // 使用指定的容量进行HashMap的初始化
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }
    // 初始化一个只能由 LinkedHashSet使用的HashSet集合 , 并且指定负载因子和初始容量
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
    // 将一个集合的元素添加到HashMap中
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

HashSet常用方法

    // HashSet的长度
    public int size() {
        return map.size();
    }
    // 如果此集合不包含任何元素,则返回true
    public boolean isEmpty() {
        return map.isEmpty();
    }
    // 如果此集合包含指定元素 , 则返回true
    public boolean contains(Object o) {
        return map.containsKey(o);
    }
    // 添加一个元素 , 如果元素不存在HashMap则调用HashMap的put()方法添加并返回true , 否则的话不进行任何操作并且直接返回false 
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    // 移除一个元素 , 如果元素不存在HashMap则调用HashMap的remove()方法移出并返回true , 否则的话不进行任何操作并且直接返回false 
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }
    // 从此集合中移除所有元素。此调用返回后,该集合将为空。
    public void clear() {
        map.clear();
    }

总结

通过源码我们可以看出 , HashSet的底层通过HashMap来实现的 , 而HashMap在1.7之前使用的是数组+链表 , 在1.8之后使用的是数据+链表+红黑树实现 , 因为HashMap的无序 , 不可重复及线程不安全 , 所以HashSet也是如此 , 通常往HashSet中重复添加元素时并不会覆盖

相关文章
|
2天前
|
搜索推荐 前端开发 Java
java医院绩效考核管理系统项目源码
系统需要和his系统进行对接,按照设定周期,从his系统获取医院科室和医生、护士、其他人员工作量,对没有录入信息化系统的工作量,绩效考核系统设有手工录入功能(可以批量导入),对获取的数据系统按照设定的公式进行汇算,且设置审核机制,可以退回修正,系统功能强大,完全模拟医院实际绩效核算过程,且每步核算都可以进行调整和参数设置,能适应医院多种绩效核算方式。
4 0
|
3天前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
|
3天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
|
3天前
|
设计模式 存储 JavaScript
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
|
3天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
|
3天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
3天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
|
3天前
|
Java 调度
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
30 1
|
Java
Java HashSet LinkedHashSet TreeSet类源码解析
Set集合中不含有重复的元素,插入重复的元素会失败。常用的有HashSet LinkedHashSet TreeSet。HashSet是无序的集合,LinkedHashSet中的排序和插入成功的顺序一致重复插入,TreeSet中元素是有序排列的,排序的依据是自身的comparator如果为null则根据key从小到大排序。
2150 0
|
Java 算法
HashSet源码解析(基于Java8)
List保证元素的添加顺序,元素可重复 Set不保证元素的添加顺序,元素不可重复 public class Test { public static void main(String[] arg...
1083 0