LinkedHashMap学习
一、概述
LinkedHashMap继承自HashMap,是Map接口的一个具体实现,它是有序的,可以按照插入顺序先后和访问时间先后进行排序,选择哪种排序方式取决于在新建LinkedHashMap的时候是否指定了accessOrder为true。如果不指定,accessOrder默认为false,LinkedHashMap会按照插入顺序进行排序;入股指定为true,则会按照LRU算法将最少访问的元素排在前面。
LinkedHashMap中的removeEldestEntry(Map.Entry)方法默认返回false,如果重写,如:
private static final int MAX_ENTRIES = 100;
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_ENTRIES;
}
,则当节点达到100,再插入新节点就会删除过时的链表头部的节点。
LinkedHashMap提供了所有可选的Map操作,并允许插入null。因为要多维护一个链表,其性能可能略低于HashMap。但是,有一个例外:对LinkedHashMap的集合视图的迭代需要时间与map大小成正比,而不管其容量。 HashMap上的迭代可能会花销更大,需要的时间与其容量成正比。也就是说capacity 的大小对其性能影响没有对HashMap的大。
LinkedHashMap的实现是非同步的。当涉及到多个线程访问并且有线程改变其结构时,必须在外部进行同步。通常对使用map的对象进行同步来完成同步操作。如果不存在这样的对象,则应该使用Collections.synchronizedMap方法包裹该map。而且最好在创建时包裹,以防止不同步访问:
Map m = Collections.synchronizedMap(new LinkedHashMap(...));
这里,需要注意的是map节点的值改变不会导致结构改变,结构改变是指添加、删除节点或者修改顺序引起的改变。
LinkedHashMap继承了HashMap的fail-fast(快速失败)机制,该机制的实现是通过一个modCount变量来记录修改次数,在每次调用会导致LinkedHashMap结构改变的方法的时候就比较下理论上的修改次数和当前修改次数的值。如果相等则允许操作,并将modCount加1,如果不相等则抛出ConcurrentModificationException异常。这种机制只能用来检测错误,无法保证一定起效。
二、结构
LinkedHashMap之所以能够进行排序,是因为它在HashMap的“数组+链表”的结构上还维护了一个双向链表,其节点结构可以参考如下的图(这里重点关注before和after节点):

(图1)
其整体结构可以参考如下的图(图上半部分的“数组+链表”结构继承自HashMap,绿色的箭头代表图1中的next,排序的实现主要通过下面的双向链表):

(图2来自:http://blog.csdn.net/luanlouis/article/details/43017071)
三、源码分析
构造函数:

这里注意到第四个构造函数,如果指定第三个参数为true会开启按访问时间排序。另外几个构造函数都有设置accessOrder = false。
属性:

accessOrder已经说明过了。剩下的,head代表的是双向链表的头部,表示最久未被访问的节点。tail代表的是双向链表的尾部,表示最近一次访问的节点。
方法:

这里可以重点看下afterNodeAccess方法,调用put,putAll,putIfAbsent,get,getOrDefault,compute,computeIfAbsent,computeIfPresent或merge方法时都将调用该方法。而调用该方法时,如果accessOrder为true,且当前操作的节点在方法调用后存在,则会移动当前操作的节点至双向链表尾部。
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last;
if (accessOrder && (last = tail) != e) {
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;
}
}
其他方法介绍可参考:
http://blog.csdn.net/u014634338/article/details/78494051
四、总结
LinkedHashMap继承于 HashMap,相当于在HashMap的基础上添加了顺序访问的功能,而方法的操作也是基于HashMap之上,增加了对提供顺序访问功能的双向链表的维护。
LinkedHashMap学习的更多相关文章
- Java学习之LinkedHashMap学习总结
前言: 在学习LRU算法的时候,看到LruCache源码实现是基于LinkedHashMap,今天学习一下LinkedHashMap的好处以及如何实现lru缓存机制的. 需求背景: LRU这个算法就是 ...
- Java LinkedHashMap学习
以前一直使用HashMap,今天学习一下LinkedHashMap JavaDoc 注解: Hash table and linked list implementation of the Map i ...
- HashMap,TreeMap,LinkedHashMap学习
Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复了覆盖了),但允许值重复.Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快 ...
- java集合类学习笔记之LinkedHashMap
1.简述 LinkedHashMap是HashMap的子类,他们最大的不同是,HashMap内部维护的是一个单向的链表数组,而LinkedHashMap内部维护的是一个双向的链表数组.HashMap是 ...
- JDK源码学习笔记——LinkedHashMap
HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序. LinkedHashMap保证了元素迭代的顺序.该迭代顺序可以是插入顺序或者是访问顺序.通过维护一个 ...
- 【Java学习笔记】HashMap子接口---LinkedHashMap
特点: 存入元素的顺序 与 取出元素的顺序相同(与LinkedHashSet类似) import java.util.HashMap; import java.util.Iterator; i ...
- LinkedHashMap源码学习
描述 可以按照添加元素的顺序对元素进行迭代的HashMap的子类. 注意,上面说的是加元素的顺序.也就是说,更新元素时,是不会影响遍历结构的的.除非设置参数accessOrder为true,将更新元素 ...
- Java集合学习(5):LinkedHashMap
一.概述 HashMap是无序的,HashMap在put的时候是根据key的hashcode进行hash然后放入对应的地方.所以在按照一定顺序put进HashMap中,然后遍历出HashMap的顺序跟 ...
- 学习JDK1.8集合源码之--LinkedHashMap
1. LinkedHashMap简介 LinkedHashMap继承自HashMap,实现了Map接口. LinkedHashMap是HashMap的一种有序实现(多态,HashMap的有序态),可以 ...
随机推荐
- Softmax 函数的特点和作用
---------- 因为这里不太方便编辑公式,所以很多公式推导的细节都已经略去了,如果对相关数学表述感兴趣的话,请戳这里的链接Softmax的理解与应用 - superCally的专栏 - 博客频道 ...
- Linux服务器运行环境搭建(四)——Tomcat安装
官网地址:http://tomcat.apache.org 官网下载地址(Tomcat6):http://tomcat.apache.org/download-60.cgi,Windows下载wind ...
- hihoCoder1599 bfs
特殊的剪枝,整体上和辗转相除法有点像 #1599 : 逃离迷宫4 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi被坏女巫抓进一座由无限多个格子组成的矩阵迷宫. 小 ...
- 20179223《Linux内核原理与分析》第三周学习笔记
测试3的实验: 1. 用gcc -g编译vi输入的代码 2. 在main函数中设置一个行断点 3. 在main函数增加一个空循环,循环次数为自己学号后4位,设置一个约为学号一半的条件断点 4. 提交调 ...
- python发送邮件的实例代码(支持html、图片、附件)
转自http://www.jb51.net/article/34498.htm 第一段代码 #!/usr/bin/python# -*- coding: utf-8 -*- import emaili ...
- BZOJ4145 [AMPPZ2014]The Prices
题意 你要购买m种物品各一件,一共有n家商店,你到第i家商店的路费为d[i],在第i家商店购买第j种物品的费用为c[i][j],求最小总费用. \(n \leq 100,m \leq 16\) 分析 ...
- elixir mix开发入门
备注: 简单使用mix 进行项目的生成,同时添加docker 构建支持 1. 生成项目 mix new mydemoproject 输出信息如下: * creating README.md * cre ...
- java I/O进程控制,重定向 演示样例代码
java I/O进程控制,重定向 演示样例代码 package org.rui.io.util; import java.io.*; /** * 标准I/O重定向 */ public class Re ...
- FastAdmin 前端页面传参笔记
FastAdmin 前端页面传参笔记 看到 QQ 群里的小伙伴询问如何传参,然后在社区里找到一笔记帖子 1 还要参考在线文档控制器部分2. 引用 Karson 的回复: 如果我们需要自己在控制器中透传 ...
- IIS注册Framework4.0
打开iis,确认一下framework4.0是否已经安装. 开始->控制面板->管理工具->Internet信息服务->应用程序池(左边栏)->观察右边主界面.net f ...