一、概述
LinkedHashSet类也是集合家族中的一员,LinkedHashSet类是Set类的一个实现,具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序。那么具体如何实现,请看源码解析。
二、源码解析
1. 类的声明
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable
LinkedHashSet类继承自HashSet类,同时实现了Set接口、Cloneable接口以及Serializable接口,这个结构和ArrayList类的结构很相似,我们仔细分析一下:
* 继承HashSet类,可以自己实现父类的方法(虽然源码里没有,万一以后有呢)。
* 实现Set接口,一是为了增加可读性,清晰看到实现的接口,二是降低维护成本,如果HashSet类不实现Set了,LinkedHashSet类也不受影响。
* Cloneable接口也是克隆标记接口,表示此类可以被克隆,此类的实例可以调用clone()方法;未实现Cloneable接口的类的实例调用clone()方法会报错,在Object类中已经定义。
* Serializable接口是序列化标记接口,表示此类可以被序列化到内存中。目的是为类可持久化,比如在网络传输或本地存储,为系统的分布和异构部署提供先决条件。
2. 构造函数
// 传入容量和装载因子
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的构造方法,而HashSet中又调用了LinkedHashMap类中的构造方法。源码如下:
//HashSet类中的构造函数
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
//LinkedHashMap类中的构造函数
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
这样我们就能清晰的了解到,LinkedHashSet类创建的实例是遵循了LinkedHashMap中排序规则accessOrder为false, 也就是会按照插入顺序进行排序(在创建新节点的时候,把该节点放到了尾部) 。
3. 迭代器
// 可分割的迭代器, 主要用于多线程并行迭代处理时使用
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}
三、总结
LinkedHashSet类是我们了解集合大家庭族谱中的一个环节,LinkedHashSet类重要的知识点有如下几点:
1. LinkedHashSet的底层使用LinkedHashMap存储元素。
2. LinkedHashSet是有序的,它是按照插入的顺序排序的,不支持按元素访问顺序排序。
敬请期待《 我的jdk源码(十九):TreeMap 》。
更多精彩内容,敬请扫描下方二维码,关注我的微信公众号【Java觉浅】,获取第一时间更新哦!