java集合系列十一:HashSet源码解析

你应该先阅读java集合系列一:前传

java集合系列十一:HashSet源码解析_第1张图片
你应该先学习HashMap

介绍

  • 不能包含重复元素
  • 无序的
  • 底层使用HashMap
  • 允许存储null值
  • 不是线程安全的
  • 具有fail-fast机制

继承关系 继承类介绍

  • AbstractSet:该类提供了Set接口的基本实现,以减少实现该类所需要的工作
  • Set:不包含重复元素的集合的顶层接口
  • Cloneable:可被克隆
  • Serializable:可被序列化

源码解析 变量解析 构造函数 常用方法解析

变量解析

	// map HashSet是通过HashMap实现的
    private transient HashMap map;
    // HashMap的value  用来占位的虚值
    private static final Object PRESENT = new Object();

构造函数

   //默认的构造函数
    HashSet()
    //构造一个包含指定集合的新集合
    HashSet(Collection < ? extends E > c){
		/*
			为什么要在指定初始容量的地方做这个计算?
			先说c.size()/.75f) + 1,首先要知道HashMap的阈值计算是
			16  * 0.75,这里通过c的size/0.75+1得到c需要的初始容量
			举个例子:c的zise = 50 / .75 + 1 = 67
			67就是初始容量,阈值 = 67 * 0.75 = 50 结果刚好是c的size
			这样新创建HashMap的初始容量阈值就刚好是c的size了
		

			再说这个16:如果c.size()/.75f) + 1得到的结果小于16,那么还是指定默认的
			初始容量

			为什么是16? 整数次幂的原因 HashMap再细说吧.
		*/
		map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
	}
    //指定初始容量和指定负载因子
    HashSet( int initialCapacity, float loadFactor)
    //指定初始容量
    HashSet( int initialCapacity)
    //这个构造是私有的 
    HashSet( int initialCapacity, float loadFactor, boolean dummy)

常用方法解析

add(E e)

作用:如果这个集合不包含元素e,则将指定的元素e添加到这个集合中

	public boolean add(E e) {
        /**
         * 数据用作key PRESENT用作value的占位符  
         */
        return map.put(e, PRESENT)==null;
    }
remove(Object o)

作用:删除一个元素,如果这个集合包含这样一个元素

   public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
	}

…都是用map实现的…

其他

  • 记得在写Collection时好像说了HashSet如何做到数据唯一的,这里就验证了数据唯一是因为HashMap,它不能违反HashMap唯一Key原则
  • 如果你想使用HashSet来存储你的类的对象,那么你必须覆盖hashCode()和equals()方法,否则两个逻辑上相同的对象将被认为是不同的,因为当你向集合中添加一个项时,会调用对象hashCode()类(最有可能为您的对象返回不同的哈希码)。
  • 总结一下,使用HashMap实现,HashSet不是以Key-value形式存储数据,Value使用占位符,其他需要学习HashMap来掌握了

2019/6/18 21:42:23

你可能感兴趣的:(java,java集合深入浅出)