LinkedHashMap的相关问题
LinkedHashMa结构的话是直接继承HashMap的,其所有的方法除了几个回调的方法之外都是继承HashMap的方法来实现操作的。
1. LinkedHashMap与HashMap一样,底层都是数组+单链表+红黑树,扩容机制也是相同的
2. LinkedHashMap相比HashMap的拉链式存储结果,内部额外的通过静态类Entry维护了一个双向链表
3. HashMap元素的遍历顺序不一定和元素的插入顺序相同,但LinkedHashMap通过遍历获取元素的时候,遍历顺序在一定条件下等于插入顺序的
4. LinkedHashMap可以通过构造参数accessOrder来指定双向链表是否是元素访问后改变顺序。accessOrder为true的时候,表示此元素被访问需要调用AfterNodeAccess方法将当前元素移至链表最后。为false的时候表示插入AfterNodeInsertion()需要移除最老的元素removeEldestEntry(first),但是默认为false,可以通过重写这个方法来达到限定容量,当容量达到时移除最老的元素,一般默认为是当前头结点元素。
移除最老元素其实也是一种算法LRU(Least Recently Used)近期最少使用。大致实现就是当达到设定的一个阈值,阈值可能是内存不足或者是最大容量,找到最近使用的存储元素进行移除,以确保新添加的元素可以被保存到集合中。
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
// 以下方法被官方注释起来了,意思可以通过重写人为限制数量以达到移除最老元素
private static final int MAX_ENTRIES = 100;
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_ENTRIES;
}
注意:LinkedHashMap中使用有head是指向链表的头,tail是指向链表的尾节点。
在LinkedHashMap中主要就是三个方法实现了双链表的前后引用的关联。其中AfterNodeRemoval()是在删除p节点之后,移除p节点用于前后的节点之间关系。使得p.before=null & p.after=null;AfterNodeInsertion()上面有说,意思就是插入的时候看是否需要将节点移除;最后就是AfterNodeAccess()方法。
LinkedHashMap结构中有一个新的newNode,这个与HashMap不同,这个方法被LinkedHashMap重写了。
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<K,V>(hash, key, value, e);
// 链接至尾节点
linkNodeLast(p);
return p;
}
// link at the end of list
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}