HashSet&LinkedHashSet源码解析

HashSet源码解析

由于HashSet的本质是一个HashMap,一些详细的方法分析这里就不在讲述了,参考HashMap

1.继承体系

HashSet也是Collection旗下的一个重要的类,更详细的说它是Set接口的一个重要实现类,其存储元素无序不可重复,其底层实现使用的是HashMap

在这里插入图片描述

2.核心属性

 	/*
	 * 因为HashSet底层本质上是一个HashMap,就是这个map属性
	 */
	private transient HashMap<E,Object> map;
	
    /*
     * Set是一个单列集合,而Map是双列映射,HashSet使用的是Map的key属性,
     * 而所有的value都是这个PRESENT,是一个Object对象。
     */
    private static final Object PRESENT = new Object();

3.构造方法

通过下面的构造方法,可以找到HashSet本质上就是一个HashMap,使用的是HashMap的key列来存储元素。

    /*
     * 底层调用HashMap的无参构造器创建了一个HashMap对象,为map属性赋值。
     * 而HashMap的无参构造器只会为内部的加载因子赋值为0.75,不会初始化哈希表。
     */
	public HashSet() {
        map = new HashMap<>();
    }

	/*
	 * 传入一个集合。
	 */
    public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

	/*
	 * 传入初始容量和加载因子。
	 */
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }
	
	/*
	 * 传入初始容量。
	 */
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

4.常用方法

由于Set是无序的(底层是hashMap),所有没有像List那样的get()方法,只能通过迭代器遍历。

4.1add()

   public boolean add(E e) {
        /*
         * 调用的是HashMap的put()方法,key就是e,value都是PRESENT(Object对象)
         * 也即map中所有的value都是PRESENT。
         */
        return map.put(e, PRESENT)==null; 
    }

4.2remove()

    /*
     * 调用的是HashMap的remove()方法,删除元素 
     */
	public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

4.3contains()

    //判断Set是否存在指定元素
	public boolean contains(Object o) {
        //调用的是map的containsKey()方法。
        return map.containsKey(o);
    }

4.4size()

    //查看set中的元素个数
	public int size() {
     	//返回map的size()
        return map.size();
    }

4.5isEmpty()

    //判断set中是否有元素
	public boolean isEmpty() {
        return map.isEmpty();
    }

5.LinkedHashSet

5.1源码解析

LinkedHashSet继承了HashSet,其增删改查等方法使用的都是HashSet的方法。

package java.util;

// LinkedHashSet继承自HashSet
public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = -2851667679971038690L;

    // 传入容量和装载因子
    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }
    
    // 只传入容量, 装载因子默认为0.75
    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }
    
    // 使用默认容量16, 默认装载因子0.75
    public LinkedHashSet() {
        super(16, .75f, true);
    }

    // 将集合c中的所有元素添加到LinkedHashSet中
    // HashSet中使用的是Math.max((int) (c.size()/.75f) + 1, 16)
    public LinkedHashSet(Collection<? extends E> c) {
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }
}

可以看出,LinkedHashSet的所有构造器调用的都是HashSet的同一个构造器

    /*
     * 调用的都是这个构造器,可以看出底层是new了一个LinkedHashMap。
     * 通过前面的LinkedHashMap的源码解析,我们知道其是可以实现LRU机制的,
     * 前提是accessOrder = true。接下来我们看一下LinkedHashSet可不可以实现。
     */
	HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

//                     ||
//					   ||
//					   \/
	
	/*
	 * 上面的构造器调用的是LinkedHashMap的这个构造器,其accessOrder是固定的为false
	 * 即不能实现LRU,链表只能按照元素的添加顺序进行排序。
	 */
    public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        //accessOrder固定为false,不能为其赋值,即不支持LRU。
        accessOrder = false;
    }

5.2总结

LinkedHashSet底层使用的是LinkedHashMap,其不支持LRU机制,其内部的链表只能按照元素添加的顺序排序

参考LInkedHashMap源码解析

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shstart7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值