一、介绍
前面文章中我们从源码详细介绍了继承于HashMap的LinkedHashMap,并通过图片示例讲解了LinkedHashMap是如何在HashMap的哈希表上将各个节点通过双向链表串起来的。
也讲解了基于HashMap实现的HashSet,那么是否存在类似于LinkedHashMap原理的一种Set集合?答案是肯定的,而且是我们本篇文章要讲的LinkedHashSet
顾名思义,LinkedHashSet是基于LinkedHashMap实现的一个Set集合。
另外,本片文章虽然不长,但是对前置知识点有着很强的依赖,需要掌握的前置知识有:HashMap(必选)、红黑树(可选)、LinkedHashMap(必选)、HashSet(必选)
二、类的声明
public class LinkedHashSet<E> extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable
从类的声明中可以看到
- 继承HashSet,表示LinkedHashSet是对HashSet的扩展。
- 实现set接口,满足Set集合的定义
- 实现了Cloneable接口,提供了对象克隆方法,但请注意,是浅克隆。
- 实现了Serializable接口,支持序列化。
三、构造方法
前面我们在讲HashSet的构造方法时,其中有一个构造方法我们做了特殊对待,如下所示
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
该构造方法创建的map对象的类型是LinkedHashMap
,不同于其他构造方法创建的HashMap
对象。
而且我们有个关键点不要忽略,在LinkedHashMap中,双向链表的遍历顺序通过构造方法指定,如果没有指定,则使用默认顺序为插入顺序,即accessOrder=false
。因此,上面的构造方法所创建的LinkedHashMap对象的双向链表遍历顺序为插入顺序。
且该构造方法就是为了给其子类LinkedHashSet使用的。我们往下看
无参构造
创建LinkedHashMap实例为内部属性,并指定底层哈希表的初始容量为16,加载因子为0.75
public LinkedHashSet() { super(16, .75f, true); }
指定初始容量
创建LinkedHashMap实例为内部属性,并指定底层哈希表的初始容量为initialCapacity,加载因子为0.75
public LinkedHashSet(int initialCapacity) { super(initialCapacity, .75f, true); }
指定初始容量和加载因子
创建LinkedHashMap实例为内部属性,并指定底层哈希表的初始容量为initialCapacity,加载因子为loadFactor
public LinkedHashSet(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor, true); }
通过集合构造
虽然说LinkedHashSet的底层是LinkedHashMap,但终究还是哈希表+双向链表,需要对哈希表的容量进行计算以避免频繁的扩容。
创建LinkedHashMap实例作为内部对象后,通过
addAll()
方法将集合中的元素逐一保存,addAll()
方法作为一个批量保存模版由其父类AbstractCollection
提供,其中的add()
方法由父类HashSet
实现,这是设计模式—模版方法的体现。public LinkedHashSet(Collection<? extends E> c) { super(Math.max(2*c.size(), 11), .75f, true); addAll(c); } public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; }
四、最后
看了LinkedHashSet的源码后,发现它只提供了以上几个构造函数,却没有提供各个方法。这是因为它继承于HashSet
,因此HashSet
中提供的方法都是可以被LinkedHashSet对象调用的,如add()、remove()、contains()等方法。所以不再过多介绍,
五、结论
- LinkedHashSet内部维护一个LinkedHashMap对象,其底层数据结构为哈希表+链表+红黑树+双向链表
- LinkedHashSet对内部双向链表的遍历顺序为插入顺序
纸上得来终觉浅,绝知此事要躬行。
————————————————我是万万岁,我们下期再见————————————————