您的位置:首页 > 理论基础 > 数据结构算法

基础数据结构之LinkedHashMap源码分析

2017-12-14 14:57 537 查看
[b]1.LinkedHashMap数据结构是双向循环链表[/b]
 LinkedHashMap节点中得知相关内容,Node节点中存在before,after,双向链表特性

 源码如下

/**
* 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;
Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
super(hash, key, value, next);
}


e = header; e != header ;e = e.after 循环链表特性

源码如下:

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)//是否包含value,遍历整个链表查看元素是否存在
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;
}


 LinkedHashMap初始化源码如下:

  

/**
* Called by superclass constructors and pseudoconstructors (clone,
* readObject) before any entries are inserted into the map.  Initializes
* the chain.
*/
void init() {
header = new Entry<K,V>(-1, null, null, null);
header.before = header.after = header; //一个节点前驱指针和后继指针都指向自己
}


2.LinkedHashMap添加新元素

 

/**
* This override alters behavior of superclass put method. It causes newly
* allocated entry to get inserted at the end of the linked list and
* removes the eldest entry if appropriate.
*/
void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);	//数组中索引放入元素 && 新元素插入到双向循环链表中
// Remove eldest entry if instructed, else grow capacity if appropriate
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) { 	        //元素相同,移除old Entry元素
removeEntryForKey(eldest.key);
} else {
if (size >= threshold)                     //如果有效元素size > 扩容因子*size
resize(2 * table.length);              //按照两倍大小容量扩容
}
}

/**
* 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<K,V>(hash, key, value, old);//创建一个新的Entry节点
table[bucketIndex] = e;                             //新的Entry节点,放入到table数组中,table数组是HashMap类的属性
e.addBefore(header);                                //新的Entry节点,插入到双向循环链表中
size++;                                             //有效元素大小+1
}


3.LinkedHashMap获取访问元素特性

public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key); 	//调用父类HashMap方法获取元素
if (e == null)
return null;
e.recordAccess(this);       			//访问后,对该访问痕迹进行记录,然后重新排序。从而实现LRU淘汰最久未使用的元素
return e.value;
}

/**
* This method is invoked by the superclass whenever the value
* of a pre-existing entry is read by Map.get or modified by Map.set.
* If the enclosing Map is access-ordered, it moves the entry
* to the end of the list; otherwise, it does nothing.
*/
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {     			//如果打开了accessOrder开关
lm.modCount++;     			//访问记录modCount自增1
remove();
addBefore(lm.header);     		//访问的元素,前面移动
}
}


     优化后的代码

public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key);
if (e == null)
return null;
if(e.accessOrder) //如果打开了accessOrder开关,进行排序。可以省略强制转化的效率
e.recordAccess(this);
return e.value;
}

总结:

   1.数据结构特性可以叠加使用。数组特性增加链表特性,可以进行扩容元素属性。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 源码 链表