前言
LinkedHashSet是Set集合的一个实现,具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序。
那么LinkedHashSet和LinkedHashMap有什么区别?它又是如何实现链表的?今天我们就从java8版本来看看LinkedHashSet是如何实现的。
源码
在java8中,我们看到LinkedHashSet源码非常简单:
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); } public LinkedHashSet(int initialCapacity) { super(initialCapacity, .75f, true); } public LinkedHashSet() { super(16, .75f, true); } public LinkedHashSet(Collection<? extends E> c) { super(Math.max(2*c.size(), 11), .75f, true); addAll(c); } @Override public Spliterator<E> spliterator() { return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED); } } 复制代码
可以看到几乎没有重写任何函数,那么它与HashSet不就一样了么?它的链表是怎么实现的呢? 这个秘密实际是在HashSet的构造函数中,它的几个构造函数源码如下:
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); } HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); } 复制代码
可以看到HashSet中维护了一个Map,它的几个构造函数中除了最后一个三参数的构造函数,其他都使用了HashMap,而三参数构造函数则使用了LinkedHashMap。
回头看LinkedHashSet,它的构造函数都调用到HashSet的这个三参数的构造函数,而LinkedHashMap本身是有链表结构的,所以LinkedHashSet是通过LinkedHashMap实现了链表。
所以LinkedHashSet的实现还是LinkedHashMap,其实可以看到在java8中HashSet的实现其实都是HashMap。