LinkedHashMap 原理

基于jdk1.8

HashMap原理:http://www.cnblogs.com/zhaojj/p/7805376.html

LinkedHashMap 继承HashMap
没有重写put resize等方法 因此基本数据结构是相同的数组、链表、红黑树

说说不同:
一、最基本元素存储单元

static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
还是原HashMap的,多了两个引用before,after,说明这是要用双向链表了

二、初始化 构造方法

public LinkedHashMap() {
super();
accessOrder = false;
}
多了 accessOrder = false; /**
* The iteration ordering method for this linked hash map: <tt>true</tt>
* for access-order, <tt>false</tt> for insertion-order.
*
* @serial
*/
final boolean accessOrder;
accessOrder表示迭代顺序,true表示访问顺序,false表示插入顺序。 后面用到再具体分析

三、put方法

put方法没有重写,因此和HashMap是一样的,但也有不同,不同在于LinkedHashMap实现了afterNodeAccess,afterNodeInsertion方法
看HashMap put源码

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e); //这个方法HashMap是空实现,这里是发生hash冲突后,找到有相同key对值进行处理时调用
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict); //这个方法HashMap也是空实现,这里是完成新数据put后调用
return null;
} LinkedHashMap具体实现
1.void afterNodeAccess(Node<K,V> e) { // move node to last 注释就说明了是把该元素移到最后
LinkedHashMap.Entry<K,V> last;
if (accessOrder && (last = tail) != e) { //accessOrder用到了,默认false等于不运行,true时是按插入顺序
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a != null)
a.before = b;
else
last = b;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
以上代码看出在按插入顺序时,在有相同key时,对当前节点将其移到链表末尾 2.void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
removeEldestEntry 方法在jdk1.8中固定返回false,因此不用关注此方法
说明一下removeElestEntry用于定义删除最老元素的规则。一旦需要删除最老节点,那么将会调用removeNode删除节点。 举个例子,如果一个链表只能维持100个元素,那么当插入了第101个元素时,以如下方式重写removeEldestEntry的话,那么将会删除最老的一个元素

四、get方法
get进行了重写

 public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
} 唯一需要关注的就是在插入模式中,获取值后又一次进行把当前节点移到链表尾部操作

五、其它
1.需要注意HashMap中TreeNode 即红黑树的节点类是继承LinkedHashMap.Entry
在HashMap中没有使用双向链表,before, after没有使用,单纯的红黑树
在LinkedHashMap中,存取等使用的也使用红黑树,但维护了before, after的链表属性,在存取时一样使用红黑树算法,但keySet()、values()以及entrySet()等迭代时使用的是双向链表来进行的

即存取是一样 但遍历不同,LinkedHashMap把所有插入的元素又全部重新维护了一个双向链表遍历时用的是这个链表,它的有序就是靠这个链表了玩的。简单理解就是和hashmap都一样,只是加了个双向链表的结构用于遍历体现有序性。

2.LinkedHashMap只有在使用三个参数的构造方法并制定accessOrder为true时,才有顺序,不指定那么和HashMap基本没什么大的区别
所谓的顺序是指插入顺序,而不是通常意义上的大小顺序

java8 LinkedHashMap 原理的更多相关文章

  1. LinkedHashMap原理

    作者:艺旭家 链接:https://www.jianshu.com/p/8f4f58b4b8ab 总结 LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的. Ha ...

  2. 图解LinkedHashMap原理

    1 前言 LinkedHashMap继承于HashMap,如果对HashMap原理还不清楚的同学,请先看上一篇:图解HashMap原理 2 LinkedHashMap使用与实现 先来一张LinkedH ...

  3. JDK source 之 LinkedHashMap原理浅谈

    注:本文参考JDK1.7.0_45源码. LinkedHashMap是基于HashMap实现的数据结构,与HashMap主要的不同为每个Entry是使用双向链表实现的,并且提供了根据访问顺序进行排序的 ...

  4. java8 HashTable 原理

    HashTable原理 Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现.Hashtable中的方法是同步的,而HashMap方法(在 ...

  5. Java基础之LinkedHashMap原理分析

    知识准备HashMap 我们平时用LinkedHashMap的时候,都会写下面这段 LinkedHashMap<String, Object> map = new LinkedHashMa ...

  6. LinkedHashMap原理以及场景

    http://www.cnblogs.com/xiaoxi/p/6170590.html

  7. Java集合之LinkedHashMap

    一.初识LinkedHashMap 上篇文章讲了HashMap.HashMap是一种非常常见.非常有用的集合,但在多线程情况下使用不当会有线程安全问题. 大多数情况下,只要不涉及线程安全问题,Map基 ...

  8. 图解集合6:LinkedHashMap

    初识LinkedHashMap 上两篇文章讲了HashMap和HashMap在多线程下引发的问题,说明了,HashMap是一种非常常见.非常有用的集合,并且在多线程情况下使用不当会有线程安全问题. 大 ...

  9. java8Stream原理深度解析

    Java8 Stream原理深度解析 Author:Dorae Date:2017年11月2日19:10:39 转载请注明出处 上一篇文章中简要介绍了Java8的函数式编程,而在Java8中另外一个比 ...

随机推荐

  1. 基于SincNet的原始波形说话人识别

    speaker recognition from raw waveform with SincNet Mirco Ravanelli, Yoshua Bengio 作为一种可行的替代i-vector的 ...

  2. Java连载41-this关键字其他注意事项、static方法

    一.this关键字 1.this在多数情况下都会省略 2.this不能用在含有static的方法之中. 3.static的方法的调用是不需要对象的,直接使用格式:类名.方法名:没有当前对象,自然不能访 ...

  3. 1+x证书web前端开发jquery专项练习测试题

    javascript程序设计-题库 1.下面哪一种不属于Jquery的选择器? A. 基本选择器 B. 层次选择器 C. 表单选择器 D. 节点选择器 答案: D 2.如果需要匹配包含文本的元素,用下 ...

  4. [03-2]VS2017 创建 ASP.NET Core Web 程序

    VS2017 创建 ASP.NET Core Web 程序 本文作者:梁桐铭- 微软最有价值专家(Microsoft MVP) 文章会随着版本进行更新,关注我获取最新版本 本文出自<从零开始学 ...

  5. Java泛型类型擦除与运行时类型获取

    Java的泛型大家都知道是类型擦除的方式实现的,“编译器会进行泛型擦除”是一个常识了(实际擦除的是参数和自变量的类型).“类型擦除” 并非像许多开发者认为的那样,在 <..> 符号内的东西 ...

  6. 黄聪:不使用 webpack,vuejs 异步加载模板

    webpack 打包不会玩,整了这么个小玩具 一段 vue 绑定代码,关键点在 gmallComponent 1.异步加载外部 vue 文件(非 .vue) 2.按一定规则拆分 template.sc ...

  7. element UI 调整表格行高

    使用element UI的table默认属性,绘制表格如下: 该表格的行高太大了,于是想调小一些. 查看官网的文档,table有几个属性, row-style:行的 style 的回调方法,也可以使用 ...

  8. SSM(七)在JavaWeb应用中使用Redis

    前言 先来看一张效果图: 作用就是在每次查询接口的时候首先判断Redis中是否有缓存,有的话就读取,没有就查询数据库并保存到Redis中,下次再查询的话就会直接从缓存中读取了.Redis中的结果:之后 ...

  9. django4-模板进阶

    1.模板系统的语法 引用变量数据: {{  }} 标签逻辑操作:{%...%} 2.变量 变量名由字符数字下划线组成 ,可以执行由视图函数传过来的对象的方法和属性 ,但是视图函数中如果使用 ' . ' ...

  10. 移动端rem适应布局

    移动端rem适应布局 rem rem(root em)是一个相对单位,类似于em,em是父元素字体大小. 不同的是rem的基准是相对于html元素的字体大小. 比如,根元素(html)设置font-s ...