//LinkedHashMap继承了HashMap,他和HashMap相比维持了一个插入时候的顺序。LinkedHashMap和HashMap之间也是一种模板设计模式的体现
//先看构造函数
public LinkedHashMap() {
super();
//排序规则false按照插入顺序读出,true最近最少使用可用于做LRU(Least Recently Used)缓存
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super(m);
accessOrder = false;
}
//覆盖HashMap中的init钩子方法。
void init() {
header = new Entry<>(-1, null, null, null);
header.before = header.after = header;
}
//在新增的时候会调用父类的方法
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
//这句代码是关键,这也是个钩子方法.执行LinkedHashMap里面的recordAccess方法。
e.recordAccess(this);
return oldValue;
}
}
modCount++;
//这句又被覆盖了
addEntry(hash, key, value, i);
return null;
}
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
//如果是LRU模式
if (lm.accessOrder) {
lm.modCount++;
//删除了自己
remove();
//在把自己重新加入队列中,这样headed.after永远都是在队列中最不常用的。
addBefore(lm.header);
}
}
private void remove() {
before.after = after;
after.before = before;
}
//调用remove()的时候会调用这个方法
void recordRemoval(HashMap<K,V> m) {
remove();
}
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);
}
}
//也是覆盖了父类的方法
void createEntry(int hash, K key, V value, int bucketIndex) {
1 HashMap.Entry<K,V> old = table[bucketIndex];
2 Entry<K,V> e = new Entry<>(hash, key, value, old);
3 table[bucketIndex] = e;
1,2,3的步骤和HashMap的操作一直
e.addBefore(header);
size++;
}
//这个覆盖了父类在扩容时候的元素迁移
void transfer(HashMap.Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
//从header双向列表开始迁移比原来的transfer直接从entry[]上更加快,效率更高
for (Entry<K,V> e = header.after; e != header; e = e.after) {
if (rehash)
e.hash = (e.key == null) ? 0 : hash(e.key);
int index = indexFor(e.hash, newCapacity);
e.next = newTable[index];
newTable[index] = e;
}
}
//构建了一个双向链表将元素插到了head的前面,head.before的后面,也就是按顺序插入
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
//获取元素
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;
}
//回到初始状态
public void clear() {
super.clear();
header.before = header.after = header;
}
//重新覆盖了containsValue方法直接从header开始遍历效率更高
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;
}
//在调用map.entry遍历的时候覆盖了newEntryIterator方法。
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() { return nextEntry(); }
}
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;
}
//从head开始挨个遍历这样也就保证了FIFO顺序
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;
}
}
/**
总结:LinkedHashMap继承了HashMap.内部维护了一个双向链表来保证可以按照顺序取出或者按照最少被使用来取出元素。
他的遍历方法直接从内部的双向链表遍历,这样效率更高。
这个类也是模板设计模式的最佳体现。几个钩子方法的使用很精妙。
*/
分享到:
相关推荐
JavaLinkedHashMap源码解析Java开发Java经验技巧共7页.pdf.zip
主要为大家解析了Java中LinkedHashMap源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
主要为大家详细介绍了Java集合系列之LinkedHashMap源码分析,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
主要介绍了Java集合框架源码分析之LinkedHashMap详解,内容包括了linkedhashmap的简介和源码剖析以及关于LinkedHashMap的源码总结,内容丰富,需要的朋友可以参考下。
LinkedHashMap源代码,Java中Map的一种实现子类。
这是关于Java学习的主要针对LinkedHashMap的实现原理
无序的 HashMap ,按 key 排序的 TreeMap ,那么 LinkedHashMap特点在哪呢 – 维护插入的顺序.LinkedHashMap 也同样出自于 Bloch之手(开发了整个 Java 集合框架的男人). 元素存储关系 红黄箭头:元素添加顺序 蓝...
这个demo主要讲解了LinkedHashmap的使用,希望可以帮助需要的同学.
java中HashMap,LinkedHashMap,TreeMap,HashTable的区别
HashMap,HashTable,LinkedHashMap,TreeMap的区别
深入Java集合学习系列(四): LinkedHashMap的实现原理
LinkedHashMap是Java中的一种特殊类型的HashMap,它保留了插入顺序,即按照元素插入的先后顺序进行排序
·企业级笔试面试题目深入源码级讲解,拒绝死记硬背 4.代码量更大、案例更丰富、更贴近实战: ·Java语言基础阶段:12720行代码,Java语言高级阶段:11684行代码 ·课堂实战项目3套,课后实战项目2套 ·近百道企业...
今天说一下LinkedHashMap的主要点,因为有同学不太清楚它和HashMap的区别。今天大概总结一下,也是方便自己进行学习。 写在前面 LinkedHashMap的内部维护了一个双向链表。可以按照元素的插入顺序进行访问,也可以...
在理解了#7 介绍的HashMap后,我们来学习LinkedHashMap的工作原理及实现。首先还是类似的,我们写一个简单的LinkedHashMap的程序: LinkedHashMap<String> lmap = new LinkedHashMap(); lmap.put(语文, 1)...
Java集合系列(LinkedHashMap+LinkedList+ArrayList)
主要介绍了 java HashMap,TreeMap与LinkedHashMap的详解的相关资料,这里提供实例代码,帮助大家学习理解 这部分的内容,需要的朋友可以参考下
将LinkedHashMap转换为json,反之亦然 如何使用 LinkedHashMap requestData = new LinkedHashMap(); LinkedHashMap auth =新的LinkedHashMap(); auth.put(“ ServiceName”,“ Login”); auth.put(“ ...
主要介绍了Java使用LinkedHashMap进行分数排序的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下