史上最详细的LinkedHashMap详解--源码分析
2016-03-26 23:46
459 查看
史上最详细的LinkedHashMap详解–源码分析
ps.本文所有源码都是基于jdk1.6LinkedHashMap数据结构
由下面代码可知,LinkedHashMap继承自HashMap。所以它保留了HashMap的数据结构,但是与之不同的是,它自己维护了一个双向循环链表,来保证LinkedHashMap的顺序。所以LinkedHashMap实际上HashMap的数据结构+双向循环链表的结构,如图1-1所示。private transient Entry<K,V> header; //双向循环链表表头 private final boolean accessOrder; //true的话按访问顺序排序(类似LRU);false按插入顺序排序;默认是false void init() { //初始化一个双向循环链表 header = new Entry<K,V>(-1, null, null, null); header.before = header.after = header; } 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; ... }
图1-1
LinkedHashMap基础方法
LinkedHashMap的put方法public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); 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; e.recordAccess(this);//在LinkedHashMap中重写了 return oldValue; } } modCount++; addEntry(hash, key, value, i);//在LinkedHashMap中重写了 return null; }
LinkedHashMap没有对put方法重写,所以LinkedHashMap继承了HashMap的put方法,但是不一样的是LinkedHashMap重写了recordAccess和addEntry这两个函数。下面让我们分析一下这两个函数变得有什么不同。
void recordAccess(HashMap<K,V> m) { //这个函数的作用就是,如果accessOrder是true的话,那么 LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; if (lm.accessOrder) { //accessOrder默认是false lm.modCount++; remove(); addBefore(lm.header); } } 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)) { removeEntryForKey(eldest.key); } else { if (size >= threshold) resize(2 * table.length); } }
总结:LinkedHashMap的put操作,不仅包含了HashMap的put操作,而且还需要维护插入的顺序,也就是不管accessOrder是ture还是false,插入一个数据都是在双向循环链表的表尾插入数据。
LinkedHashMap的get方法
public V get(Object key) { Entry<K,V> e = (Entry<K,V>)getEntry(key); if (e == null) return null; e.recordAccess(this); //get方法中也用到了这个方法,上面有代码 return e.value; }
get方法很简单,和HashMap查找方式基本一样,但是有一点需要注意的是,如果accessOrder是ture,也就是上面所说的,那么它就会按照访问的顺序排序(类似LRU,只不过是不淘汰),也就是按照访问的顺序维护这个循环双向链表,也就是如果accessOrder是true,我需要把访问的这个key移到双向循环链表的表尾。
相关文章推荐
- 从源码安装Mysql/Percona 5.5
- 浅析Ruby的源代码布局及其编程风格
- asp.net 抓取网页源码三种实现方法
- JS小游戏之仙剑翻牌源码详解
- JS小游戏之宇宙战机源码详解
- jQuery源码分析之jQuery中的循环技巧详解
- 本人自用的global.js库源码分享
- java中原码、反码与补码的问题分析
- ASP.NET使用HttpWebRequest读取远程网页源代码
- PHP网页游戏学习之Xnova(ogame)源码解读(六)
- C#获取网页HTML源码实例
- PHP网页游戏学习之Xnova(ogame)源码解读(八)
- PHP网页游戏学习之Xnova(ogame)源码解读(四)
- JS小游戏之极速快跑源码详解
- JS小游戏之象棋暗棋源码详解
- android源码探索之定制android关机界面的方法
- 基于Android设计模式之--SDK源码之策略模式的详解
- Android游戏源码分享之2048
- C语言借助EasyX实现的生命游戏源码
- C实现的非阻塞方式命令行端口扫描器源码