java8 LinkedHashMap 原理
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 原理的更多相关文章
- LinkedHashMap原理
作者:艺旭家 链接:https://www.jianshu.com/p/8f4f58b4b8ab 总结 LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的. Ha ...
- 图解LinkedHashMap原理
1 前言 LinkedHashMap继承于HashMap,如果对HashMap原理还不清楚的同学,请先看上一篇:图解HashMap原理 2 LinkedHashMap使用与实现 先来一张LinkedH ...
- JDK source 之 LinkedHashMap原理浅谈
注:本文参考JDK1.7.0_45源码. LinkedHashMap是基于HashMap实现的数据结构,与HashMap主要的不同为每个Entry是使用双向链表实现的,并且提供了根据访问顺序进行排序的 ...
- java8 HashTable 原理
HashTable原理 Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现.Hashtable中的方法是同步的,而HashMap方法(在 ...
- Java基础之LinkedHashMap原理分析
知识准备HashMap 我们平时用LinkedHashMap的时候,都会写下面这段 LinkedHashMap<String, Object> map = new LinkedHashMa ...
- LinkedHashMap原理以及场景
http://www.cnblogs.com/xiaoxi/p/6170590.html
- Java集合之LinkedHashMap
一.初识LinkedHashMap 上篇文章讲了HashMap.HashMap是一种非常常见.非常有用的集合,但在多线程情况下使用不当会有线程安全问题. 大多数情况下,只要不涉及线程安全问题,Map基 ...
- 图解集合6:LinkedHashMap
初识LinkedHashMap 上两篇文章讲了HashMap和HashMap在多线程下引发的问题,说明了,HashMap是一种非常常见.非常有用的集合,并且在多线程情况下使用不当会有线程安全问题. 大 ...
- java8Stream原理深度解析
Java8 Stream原理深度解析 Author:Dorae Date:2017年11月2日19:10:39 转载请注明出处 上一篇文章中简要介绍了Java8的函数式编程,而在Java8中另外一个比 ...
随机推荐
- CentOs安装mysql数据库
1. 下载 http://dev.mysql.com/downloads/mysql/ 或者使用wget下载: wget http://dev.mysql.com/get/Downloads/MySQ ...
- Linux网络基础协议和ip管理
1.简述osi七层模型和TCP/IP五层模型 osi七层模型分别是:物理层.数据链路层.网络层.传输层.会话层.表示层.应用层. 1)物理层:这一层的主要功能是二进制传输数据,界定连接器和网线的规格: ...
- Vue入门、插件安装
一.Vue 1.什么是Vue? (1)官网地址: https://cn.vuejs.org/ (2)Vue是一个渐进式的JavaScript框架.采用自底向上增量开发的设计.可以简单的理解为Vue是一 ...
- HTTP中的2XX状态码
HTTP状态码分类 1XX --信息,服务器收到请求,需要请求者继续执行操作 2XX--成功,操作被成功接收并处理 3XX--重定向,需要进一步的操作以完成请求 4XX--客户端错误,请求包含语法错误 ...
- Python通用函数实现数组计算
一.数组的运算 数组的运算可以进行加减乘除,同时也可以将这些算数运算符进行任意的组合已达到效果. >>> x=np.arange() >>> x array([, ...
- [转]RHEL7上配置NFS服务
原文地址:http://380531251.blog.51cto.com/7297595/1659865 1.课程目标 了解什么是NFS及其功能: 掌握NFS的配置: 掌握NFS的验证: 能够单独熟练 ...
- Spring Boot2.1.7启动zipkin-server报错:Error creating bean with name 'armeriaServer' defined in class path
修改项目,更新组件版本时,引入了最新版本2.12.9的zipkin-server和zipkin-autoconfigure-ui时,服务启动报错: org.springframework.beans. ...
- ubuntu 查看软件包中的内容 (已经安装)
在 使用 apt 进行安装软件的时候,我们要经常判断,软件安装了什么和安装到什么地方.这时候 我们要使用 dpkg -L 命令来进行查看: 同样 在 fedora 上可以使用 rpm -ql iper ...
- js 判断当前时间是否处于某个一个时间段内
js 判断当前时间(或者所选时间)是否在某一时间段 我们可以使用 jutils - JavaScript常用函数库的 isDuringDate 函数来实现 传入 beginDateStr (开始时间) ...
- iPad替代midi键盘
下载安装rtpMIDI (网络MIDI驱动程序) 打开rtpMIDI,在“My session”那里按下+,就会自动显示你的电脑的名字 检查Bonjour服务正常运行,iPad与pc网络正常连接 iP ...