jdk1.8.0_144

  本文阅读最好先了解HashMap底层,可前往《Java集合中的HashMap类》

  LinkedHashMap由于它的插入有序特性,也是一种比较常用的Map集合。它继承了HashMap,很多方法都直接复用了父类HashMap的方法。本文将探讨LinkedHashMap的内部实现,以及它是如何保证插入元素是按插入顺序排序的。

  在分析前可以先思考下,既然是按照插入顺序,并且以Linked-开头,就很有可能是链表实现。如果纯粹以链表实现,也不是不可以,LinkedHashMap内部维护一个链表,插入一个元素则把它封装成Entry节点,并把它插入到链表尾部。功能可以实现,但这带来的查找效率达到了O(n),显然远远大于HashMap在没有冲突的情况下O(1)的时间复杂度。这就丝毫不能体现出Map这种数据结构随机存取快的优点。

  所以显然,LinkedHashMap不可能只有一个链表来维护Entry节点,它极有可能维护了两种数据结构:散列表+链表。

  为便于理解,将不会分析每个方法,会从插入开始分析LinkedHashMap的数据结构及实现。

  LinkedHashMap继承了HashMap类,并且没有重写put方法,而是直接沿用了HashMap#put方法。有关HashMap#put已经在《Java集合中的HashMap类》有了较为详细的介绍。从调用HashMap#put方法可知,它的插入过程和HashMap相同,也就是说它也一样有着和HashMap相同的散列表结构。不过要小心尽管调用的是HashMap#put方法,但在这个方法中有一个方法是构造一个新节点newNode,这里LinkedHashMap重写了,所以调用的是LinkedHashMap#newNode,也正是这个方法实现了对LinkedHashMap链表的维护。

  忽略其余代码,关键代码在HashMap#putVal中tab[i] = newNode(hash, key, value, null),稍后再来查看LinkedHashMap#newNode方法。

  其过程先用图例来说明。

  链表插入过程如下代码所示:

 //LinkedHashMap#newNode,构造一个新的节点
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<K,V>(hash, key, value, e);
linkNodeLast(p);
return p;
}  
 //LinkedHashMap#linkNodeLast,插入到链表尾部
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail; //LinkedHashMap定义了tail尾指针和head头指针,且链表为双向链表
tail = p;
if (last == null)
head = p;
else {
//双向链表的插入
p.before = last;
last.after = p;
}
}

  对于LinkedHashMap插入,散列表部分和HashMap一致,而双向链表部分则是来一个就插到尾部,这样就保证了保持插入顺序。

  通过插入基本了解了LinkedHashMap的内部实现,get方法很简单,同样是计算出key的hash和对应散列表的下标即可。

  在LinkedHashMap还需要提到三个方法,这三个方法在HashMap中定义,但是并没有具体实现,具体实现放到了LinkedHashMap中。

void afterNodeAccess(Node<K,V> p)

  此方法可以实现通过访问顺序排序,方法中如果定义accessOrder=true,则会将访问(get)过的元素放到链表尾部。accessOrder设置可以通过构造方法传递。

void afterNodeInsertion(boolean evict)

  这个方法在LinkedHashMap并无意义,因为它调用的removeEldestEntry始终返回false,此时程序就会返回不会执行。但如果重写了removeEldestEntry方法,则可以实现LRU(最近最少使用)缓存。

void afterNodeRemoval(Node<K,V> p)

  移除Map中的元素时调用,更新双向链表。

这是一个能给程序员加buff的公众号 

Java集合中的LinkedHashMap类的更多相关文章

  1. Java集合中的HashMap类

    jdk1.8.0_144 HashMap作为最常用集合之一,继承自AbstractMap.JDK8的HashMap实现与JDK7不同,新增了红黑树作为底层数据结构,结构变得复杂,效率变得更高.为满足自 ...

  2. Java集合中List,Set以及Map等集合体系详解

    转载请注明出处:Java集合中List,Set以及Map等集合体系详解(史上最全) 概述: List , Set, Map都是接口,前两个继承至collection接口,Map为独立接口 Set下有H ...

  3. Java集合中List、Set以及Map

    概述: List , Set, Map都是接口:List , Set继承至Collection接口,Map为独立接口 Set下有HashSet,LinkedHashSet,TreeSet List下有 ...

  4. java集合中List与set的区别

       java集合中List与set的区别.     List可以存储元素为有序性并且元素可以相同.     set存储元素为无序性并且元素不可以相同.     下面贴几段代码感受一下: ArrayL ...

  5. Java集合框架(常用类) JCF

    Java集合框架(常用类) JCF 为了实现某一目的或功能而预先设计好一系列封装好的具有继承关系或实现关系类的接口: 集合的由来: 特点:元素类型可以不同,集合长度可变,空间不固定: 管理集合类和接口 ...

  6. Java集合中Comparator和Comparable接口的使用

    在Java集合中,如果要比较引用类型泛型的List,我们使用Comparator和Comparable两个接口. Comparable接口 -- 默认比较规则,可比较的 实现该接口表示:这个类的实例可 ...

  7. Java集合中Set的常见问题及用法

    在这里演示的案例是衔接Java集合中的List(点击查看)那篇博文的,本节我们学习的Set的用法. Set是Collection的一个重要的子接口,Set中的元素是无序排列的,并且元素不可以重复,被称 ...

  8. Java最重要的21个技术点和知识点之JAVA集合框架、异常类、IO

    (三)Java最重要的21个技术点和知识点之JAVA集合框架.异常类.IO  写这篇文章的目的是想总结一下自己这么多年JAVA培训的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享 ...

  9. 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法

    注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...

随机推荐

  1. web端表格测试用例

    表格测试: 表格内容列表排序功能是否正常每一栏的宽度是否足够宽,表格里的文字是否都有折行?是否有因为某一格的内容太多,而将整行的内容拉长?表格是否能左(右)添加(删除)列,表格是否能上(下)添加(删除 ...

  2. QPS/TPS简介

    系统吞度量要素 一个系统的吞度量(承压能力)与request对CPU的消耗.外部接口.IO等等紧密关联.单个reqeust 对CPU消耗越高,外部系统接口.IO影响速度越慢,系统吞吐能力越低,反之越高 ...

  3. hiboCoder 1041 国庆出游 dfs+思维

    先抽象出一棵以1做为根结点的树.给定了访问序列a[1..m]. 考虑两种特殊情况: 1.访问了某个a[j],但是存在a[i]没有访问且i < j,出现这种情况说明a[j]一定是a[i]的祖先节点 ...

  4. hdu2846 Repository 字典树(好题)

    把每个字符串的所有子串都加入字典树,但在加入时应该注意同一个字符串的相同子串只加一次,因此可以给字典树的每个节点做个记号flag--表示最后这个前缀是属于那个字符串,如果当前加入的串与它相同,且二者属 ...

  5. C语言老司机学Python (二)

    标准数据类型: 共6种:Number(数字),String(字符串),List(列表),Tuple(元组),Sets(集合),Dictionary(字典) 本次学习主要是和数据类型混个脸熟,知道每样东 ...

  6. H3C单臂路由配置

    Route配置 int g0/0.1 ip add 192.168.10.1 255.255.255.0 vlan-type dot1q vid 10 #子接口封装dot1q并分配给VLAN 10 q ...

  7. windows下用pip安装软件超时解决方案

    以前介绍过ubuntu下更换更新源办法,详情见http://www.cnblogs.com/Alier/p/6358447.html 下面讲一下windows下面pip的配置更改,包括下载软件是超时错 ...

  8. SQL中partition关键字的使用

    最近在写后台语句时候,运用到了partition这样一个关键字. 先大致说一下背景,有一种数据表,如下 现在需要取出,每一个人最近的一次打卡时间. 思路是,先把数据按照人名分组,然后在每个组里面按照时 ...

  9. thinphp 整合ueditor

    我的ueditor是部署在public/editor 部署前台页面 <script type="text/javascript" > var UEDITOR_HOME_ ...

  10. MinnowBoard MAX 硬件开发板

    Minnowboard MAX MinnowBoard MAX是一款紧凑型,经济实惠,而且功能强大的开发板为专业人士和制造商.开放式的硬件设计使无尽的定制和集成的潜力.它采用64位英特尔®凌动™E38 ...