LinkedHashSet
底层为LinkedHashMap
,故本文主要围绕LinkedHashMap
展开
LinkedHashSet 简述
核心成员变量
无
构造器
1. LinkedHashSet(int initialCapacity, float loadFactor)
2. LinkedHashSet(int initialCapacity)
3. LinkedHashSet()
4. LinkedHashSet(Collection<? extends E> c)
以上函数本质都是调用父类HashSet
的HashSet(int initialCapacity, float loadFactor, boolean dummy)
构造器。
dummy
参数只是一个为了与HashSet
其他构造器区分而设计的,没有实际作用HashSet(int initialCapacity, float loadFactor, boolean dummy)
的底层是LinkedHashMap
的public LinkedHashMap(int initialCapacity, float loadFactor)
成员方法
全部继承自HashSet
LinkedHashMap
核心成员变量
transient LinkedHashMap.Entry<K,V> head
,头指针transient LinkedHashMap.Entry<K,V> tail
,尾指针final boolean accessOrder
,默认为false
。为true
时LinkedHashMap
以访问顺序排序,否则以插入顺序排序Entry<K,V>
,继承了父类的内部类Node
,仅添加了两个成员变量before
,after
,以实现双向链表。同时,由于继承了next
属性,故仍可对table
数组上同一位置的链表遍历。
HashMap.TreeNode
->LinkedHashMap.Entry
->HashMap.Node
->Map.Entry
笔者认为HashMap.TreeNode
可以直接继承HashMap.Node
,因为在实现中实际并未用到继承得来的Entry<K,V> before, after
//LinkedHashMap
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
//HashMap
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
//重写了hashCode方法
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
...
}
public final boolean equals(Object o) {
...
}
}
构造器
LinkedHashMap(int initialCapacity, float loadFactor)
LinkedHashMap(int initialCapacity)
LinkedHashMap()
LinkedHashMap(Map<? extends K, ? extends V> m)
LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder)
以上构造器本质均为调用父类HashMap
对应的构造器。
成员方法
独有方法
linkNodeLast(p)
,将结点连在原链表末尾transferLinks(LinkedHashMap.Entry<K,V> src,LinkedHashMap.Entry<K,V> dst)
,将原链表的该结点替换为新的结点
重写方法
newNode(int hash, K key, V value, Node<K,V> e)
newTreeNode(int hash, K key, V value, Node<K,V> next)
replacementNode(Node<K,V> p, Node<K,V> next)
- …
重写主要是为了适应新的数据结构,功能逻辑不变
entrySet()、keySet()、values()
功能逻辑与HashMap
相同,主要是内部类LinkedHashIterator
的nextNode
方法是按双向链表的链接遍历的。因此和HashMap
中HashIterator
的nextNode
有点区别。
注意:
LinkedEntrySet
和HashMap
类的EntrySet
分别继承自AbstractSet
类。因此二者是兄弟关系而非子父类关系。LinkedHashIterator
的nextNode
方法有别于HashIterator
的同名方法HashIterator
的nextNode
每次被调用时若next
为null
则均需要在数组中找到下一个非null
元素LinkedHashMap
由于有头指针且支持按次序访问,因此能一次访问全部非null
节点
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
}
//LinkedEntrySet
final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator<Map.Entry<K,V>> iterator() {
return new LinkedEntryIterator();
}
public final boolean contains(Object o) {
...
}
public final boolean remove(Object o) {
...
}
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
...
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
...
}
}
//LinkedHashIterator
abstract class LinkedHashIterator {
LinkedHashMap.Entry<K,V> next;
LinkedHashMap.Entry<K,V> current;
int expectedModCount;
LinkedHashIterator() {
next = head;
expectedModCount = modCount;
current = null;
}
public final boolean hasNext() {
return next != null;
}
//不同于HashMap中HashIterator的nextNode
//LinkedHashMap由于有头指针且支持按次序访问,因此能一次访问全部节点,中间不会遇到节点为null的情况。
//而HashIterator的nextNode每次被调用时若next为null则均需要在数组中找到下一个非null元素。
final LinkedHashMap.Entry<K,V> nextNode() {
LinkedHashMap.Entry<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
current = e;
next = e.after;
return e;
}
public final void remove() {
...
}
}