/*
* LinkedHashMap的底层结构一直有个困惑纠结了好久
* 它继承自HashMap,HashMap底层结构是哈希表+单链表的组合
* LinkedHashMap为了保存其数据,加入了双向循环链表来存放数据,双向链表和哈希+单向链表如何组合的呢?
* 这个问题想了很久,最后发现他们一点关系都没有!!只是Entry中既可以保存单链表指针next,也可以保存双链表
* 指针after,before,然后增加header,双联表的数据结构是单独存在的。。。
*
* LinkedHashMap继承自HashMap,增加了新的特性:
* 对存储的数据保存其存储顺序,可以根据最近使用的元素进行排序
*/
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
{
//序列化
private static final long serialVersionUID = 3801124242820219131L;
//双向链表head,Header中不存储数据
private transient Entry<K,V> header;
/**
* The iteration ordering method for this linked hash map: <tt>true</tt>
* for access-order, <tt>false</tt> for insertion-order.
*
* @serial
*/
private final boolean accessOrder;
/**
* Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
* with the specified initial capacity and load factor.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
/**
* Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
* with the specified initial capacity and a default load factor (0.75).
*
* @param initialCapacity the initial capacity
* @throws IllegalArgumentException if the initial capacity is negative
*/
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
/**
* Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
* with the default initial capacity (16) and load factor (0.75).
*/
public LinkedHashMap() {
super();
accessOrder = false;
}
/**
* Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
* the same mappings as the specified map. The <tt>LinkedHashMap</tt>
* instance is created with a default load factor (0.75) and an initial
* capacity sufficient to hold the mappings in the specified map.
*
* @param m the map whose mappings are to be placed in this map
* @throws NullPointerException if the specified map is null
*/
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super(m);
accessOrder = false;
}
/**
* Constructs an empty <tt>LinkedHashMap</tt> instance with the
* specified initial capacity, load factor and ordering mode.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @param accessOrder the ordering mode - <tt>true</tt> for
* access-order, <tt>false</tt> for insertion-order
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
/**
* HashMap中留的hook,构造器执行,添加元素前执行
*/
@Override
void init() {
header = new Entry<>(-1, null, null, null);
//初始化双向链表节点
header.before = header.after = header;
}
/**
* Transfers all entries to new table array. This method is called
* by superclass resize. It is overridden for performance, as it is
* faster to iterate using our linked list.
* 将Entrys转移到newTable中,转移时,以双链表的顺序逐个进行
*/
@Override
void transfer(HashMap.Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
//从header开始遍历向后遍历
//e=header时,遍历结束
for (Entry<K,V> e = header.after; e != header; e = e.after) {
if (rehash)
//获取hash值
e.hash = (e.key == null) ? 0 : hash(e.key);
//获取index值
int index = indexFor(e.hash, newCapacity);
e.next = newTable[index];
newTable[index] = e;
}
}
/**
* 以双链表的顺序进行遍历
*/
public boolean containsValue(Object value) {
// Overridden to take advantage of faster iterator
if (value==null) {
for (Entry e = header.after; e != header; e = e.after)
if (e.value==null)
return true;
} else {
for (Entry e = header.after; e != header; e = e.after)
if (value.equals(e.value))
return true;
}
return false;
}
/**
* 覆盖HashMap中的get(),改变链表的顺序
*/
public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key);
if (e == null)
return null;
//改变链表顺序
e.recordAccess(this);
return e.value;
}
/**
* Removes all of the mappings from this map.
* The map will be empty after this call returns.
*/
public void clear() {
//将每个单链表的first元素清空
super.clear();
//将header元素清空
header.before = header.after = header;
}
/**
* LinkedHashMap entry.
*/
private static class Entry<K,V> extends HashMap.Entry<K,V> {
// These fields comprise the doubly linked list used for iteration.
Entry<K,V> before, after;
//继承自HashMap.Entry的元素:next,hash,key,value
//初始化时,没有给before,after赋值,那它们在哪赋值的呢?
//我们会发现header为null时,after=before=header
//header不为null时,after和befor的值在addBefore时赋值
Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
super(hash, key, value, next);
}
/**
* 回收交给GC
* 双向链表remove两个指针改动
* 1.上一个节点的after设为下一个节点
* 2。下一个节点的befor设为上一个节点
*/
private void remove() {
//before。after = after
before.after = after;
//after.before = before
after.before = before;
}
/**
* 将this插入至existingEntry之前
* 在双向链表中插入元素需要做4个指针的改动
* 1.将this的上一个节点设为e的上一个节点
* 2.将this的下一个节点设为e
* 3.将上一个节点的after设为this
* 4。将e的上一个节点设为this
*/
private void addBefore(Entry<K,V> existingEntry) {
// this.before = existingEntry.before;
// this.after = existingEntry;
// existingEntry.before.after=this;
// existingEntry.before = this;
//2.将this的下一个节点设为e
after = existingEntry;
//1.将this的上一个节点设为e的上一个节点
before = existingEntry.before;
//3.将上一个节点的after设为this
before.after = this;
//4。将e的上一个节点设为this
after.before = this;
}
/**
* put和set后执行此方法,
* 作用是改变元素在链表中的顺序,实现按照 最近访问的顺序排列的功能
*/
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
//以最近访问的顺序排列时,执行操作
if (lm.accessOrder) {
lm.modCount++;
//LinkedHashMap每次插入元素时,如果远来存在数据则替换数据,替换后的顺序不是我们想要的顺序
//所以删除此元素,然后重新添加,执行addBefore
//同样的道理,执行get获得元素后,元素的存储位置也不是我们想要的顺序
remove();
addBefore(lm.header);
}
}
//hashMap中的remove值消除掉了Next指针,在这里消除befor,after的关联
void recordRemoval(HashMap<K,V> m) {
remove();
}
}
private abstract class LinkedHashIterator<T> implements Iterator<T> {
Entry<K,V> nextEntry = header.after;
Entry<K,V> lastReturned = null;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public boolean hasNext() {
return nextEntry != header;
}
public void remove() {
if (lastReturned == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
LinkedHashMap.this.remove(lastReturned.key);
lastReturned = null;
expectedModCount = modCount;
}
Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (nextEntry == header)
throw new NoSuchElementException();
Entry<K,V> e = lastReturned = nextEntry;
nextEntry = e.after;
return e;
}
}
private class KeyIterator extends LinkedHashIterator<K> {
public K next() { return nextEntry().getKey(); }
}
private class ValueIterator extends LinkedHashIterator<V> {
public V next() { return nextEntry().value; }
}
private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() { return nextEntry(); }
}
// These Overrides alter the behavior of superclass view iterator() methods
Iterator<K> newKeyIterator() { return new KeyIterator(); }
Iterator<V> newValueIterator() { return new ValueIterator(); }
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
void addEntry(int hash, K key, V value, int bucketIndex) {
super.addEntry(hash, key, value, bucketIndex);
// Remove eldest entry if instructed
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
}
}
/**
* This override differs from addEntry in that it doesn't resize the
* table or remove the eldest entry.
*/
void createEntry(int hash, K key, V value, int bucketIndex) {
HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<>(hash, key, value, old);
table[bucketIndex] = e;
e.addBefore(header);
size++;
}
/**
* 如果此映射移除其最旧的条目,则返回 true.此时容量put容量不再改变
*/
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
}
04-30
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交