在分析LinkedHashSet的时候,先看一下它的继承关系
可以看到LinkedHash继承自HashSet,即拥有HashSet的全部属性,接着来看一下源码中的注释
- Hash table and linked list implementation of the Set interface,
with predictable iteration order. This implementation differs from
HashSet in that it maintains a doubly-linked list running through
all of its entries. This linked list defines the iteration ordering,
which is the order in which elements were inserted into the set
(insertion-order). Note that insertion order is not affected
if an element is re-inserted into the set. - 这个类是实现了Set接口的哈希表跟链表。此实现类跟HashSet的区别在于它内部持有一个双链表并且存储了所有的entry。这个链表定义了迭代的顺序,该顺序就是元素被插入Set的顺序。注意如果一个元素被重复插入,迭代顺序是不会被影响的。
看到这里,感觉其实跟HashSet一个套路,底层都不是自己实现的,而是通过内部实现的一个LinkedHashMap来维护的,所谓HashSet取地是HashMap的key,HashSet取地是LinkedHashMap的Key,下面从源码的角度来验证一下。
正文
成员变量
就一个序列化Id,其余的全部继承自HashSet
private static final long serialVersionUID = -2851667679971038690L;
构造方法
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
可以发现,不管是调用哪一个构造方法,最后调用的都是调用的同一个父类方法,也就是上一篇HashSet中的一个LinkedHashMap的初始化方法,最终还是初始化了一个LinkedHashMap
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
Over
当我还想继续查看的时候,发现其实已经没有可以分析的了,没有复写HashSet的其它方法,所以,LinkedHashSet内部没有做过很多的实现,只是调用了HashSet的初始化LinkedHashMap的构造方法,剩余的操作跟HashSet实际上是一样的,没有什么区别。
总结
- LinkedHashSet中的LinkedHash跟LinkedHashMap中的LinkedHash实际上是一样的,哈希表跟链表
- LinkedHashSet跟HashSet都是非线程安全的,不允许重复元素
- LinkedHashSet都允许插入null,插入的元素需要复写hashcode跟equals方法