本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作,如有错误之处忘不吝批评指正!

絮叨絮叨

  首先呢,明白一点 LinkedHashMap是HashMap的子类,也就是说它就是一个HashMap(所以还是要对HashMap源码有一定了解),至于它可以保证(有序)先后顺序,只能说儿子比老子优秀!虎父无犬子,儿子在父亲的基业上又有了独到之处!原因呢?下面一起看看源码((基于jdk1.8)就知晓了!(看源码一定要有耐心,第一次看可能看不懂,后面再看可能还是看不懂,但是别放弃治疗)。

public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
{
}

源码分析

 变量分析

   LinkedHashMap在HashMap基础上扩展的这两个成员变量要特别注意,这两个变量是保证有序的基础

    /**
* The head (eldest) of the doubly linked list.
* 记录第一个 key—value 对象关于LinkedHashMap.Entry<K,V>的结构接下来就会分析
*/
   transient LinkedHashMap.Entry<K,V> head; /** * The tail (youngest) of the doubly linked list.
* 保存最后一个 key—value 对象
*/
transient LinkedHashMap.Entry<K,V> tail;

   

 LinkedHashMap.Entry<K,V>结构:

  它继承了HashMap.Node<K,V>,  添加了两个LinkedHashMap.Entry<K,V> 用来记录它的前一个 和后一个put进入来的key-value对象(LinkedHashMap.Entry<K,V>),在在结构设计上保证了LinkedHashMap有序的可实现

   static class Entry<K,V> extends HashMap.Node<K,V> {
//它的前一个 和后一个put进入来的key-value对象
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}

  附上HashMap.Node<K,V>

static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
//省略。。。。。。。
}

 实现

     了解完结构我们再来看看它在代码中是如何实现的,LinkedHashMap是HashMap的子类 ,在放入key-value时,它复用了HashMap的put方法

public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
} 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)
//这里要格外注意 LinkedHashMap复写了HashMap的
//newNode(hash, key, value, null) 方法
tab[i] = newNode(hash, key, value, null);
//......
}
  LinkedHashMap复写了HashMap的newNode(hash, key, value, null) 方法,代码如下:
  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;
}
/***有序的实现核心***/
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}

   举一个场景来说明上面的有序核心实现方法,比如说有这么一个场景:  一个班有 1号小明同学 2号张三 3号小红 4号李四同学,老师要知道学生进入教师的先后顺序。老师在黑板上写了 两个词  head,tail两个字段 规定:

    1.第一个来的在 head来的在head、tail写上自己的名字

    2.第二个及后续到的, 看到黑板上的tail字段后,找到这个同学(这个同学记住我之后到的 after) 通知自己到了(并记住在我之前的是这个同学before) 并修改tail字段为自己的名字

  例子:

    1.小明同学 第一个到  ,在黑板上 head,tail 都写下 小明

    2.张三到了之后看到 tail是小明 记住 自己上一个(before)是小明 ,并修改tail为张三 ,通知小明,小明记下来自己的后面(afte)r是张三

    3小红到了看到tail是张三 记住自己上一个(before)是张三 并修改tail为小红,通知张三,张三记下来自己的后面(after)是小红

    4李四到了。。。。。。。

  老师来了上课 看到head上写的是小明  并询问 小明 你后面是谁 , 小明回:小红 再询问 小红 ....知道 询问到李四 结束

  老师就知道了学生进入教室的顺序 小明->张三->小红->李四。

LinkedHashMap为什么是有序的(与put先后顺序一致)的更多相关文章

  1. 序列化LinkedHashMap,有序输出Json字符串

    LinkedHashMap本身是有序的,使用JDK自带的序列化代码或者fastJson代码序列化后,字符串并非按照插入顺序输出 Map<String,String> linkedMap=n ...

  2. 有序的Map集合--LinkedHashMap

    提出问题: 在写一个dao的时候,我的需求是这个dao是一个万能的,目前的方法只有一个查询出实体类对应的表中所有的数据,通过传入的对象,利用反射获取实体类中的属性名,属性类型,利用字符串拼接获取相应属 ...

  3. 有序的map LinkedHashMap

    HashMap是无序的,HashMap在put的时候是根据key的hashcode进行hash然后放入对应的地方.所以在按照一定顺序put进HashMap中,然后遍历出HashMap的顺序跟put的顺 ...

  4. LinkedHashMap唯一,存储取出有序

    package cn.itcast_03; import java.util.LinkedHashMap; import java.util.Set; /* * LinkedHashMap:是Map接 ...

  5. Map随笔:有序的HashMap——LinkedHashMap

    目录 Map随笔:有序的HashMap--LinkedHashMap 一,概述 二,源码结构 三,总结 Map随笔:有序的HashMap--LinkedHashMap 一,概述 ​ LinkedHas ...

  6. 【Java】Map杂谈,hashcode()、equals()、HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap

    参考的优秀文章: <Java编程思想>第四版 <Effective Java>第二版 Map接口是映射表的结构,维护键对象与值对象的对应关系,称键值对. > hashco ...

  7. Java API —— HashMap类 & LinkedHashMap类

    1.HashMap类 1)HashMap类概述         键是哈希表结构,可以保证键的唯一性 2)HashMap案例         HashMap<String,String>   ...

  8. Java基础知识强化之集合框架笔记58:Map集合之LinkedHashMap类的概述

    1. LinkedHashMap类的概述 LinkedHashMap:Map接口的哈希表(保证唯一性) 和 链接(保证有序性)列表实现,具有可预知的迭代顺序. 2. 代码示例: package cn. ...

  9. HashMap,LinkedHashMap,TreeMap的区别(转)

    Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复了覆盖了),但允许值重复.Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快 ...

随机推荐

  1. Python 代码片段整理

    1.numpy.random.shuffle(x) import numpy as np x = [] for i in range(10): x.append(i) print(x) np.rand ...

  2. Y1E001 HDI二阶板、三阶板

    简单说一下我的理解: 首先我认为几阶就是几次压合,我习惯用几次压合来形容.. 一阶板我认为就是一次压合,只能打一种机械孔,在表层把 一阶板是最普通的的多层板压合方式. 如下图所示,L2~L3为芯板CO ...

  3. vs2015配置OpenCV遇到的问题

    OpenCV的配置过程可以参考博文:https://www.cnblogs.com/linshuhe/p/5764394.html 简要记载配置过程: 1.官网下载OpenCV安装包,并解压到目录,例 ...

  4. 关于阿里ICON矢量图(SVG)上传问题.

    注意点: 1. 存储为svg格式(建议使用存储为svg,不要使用导出为svg)2. 图像位置:链接(注意哦,不要点嵌入和保留编辑功能)---确定3. AI里面选中图形,点对象-路径-轮廓化描边 软件编 ...

  5. Oracle、DB2、SQLSERVER、Mysql、Access分页SQL语句

    最近把平时在项目中常用到的数据库分页sql总结了下.大家可以贴出分页更高效的sql语句.sqlserver分页  第一种分页方法 需用到的参数:  pageSize 每页显示多少条数据  pageNu ...

  6. CSS、常用标签属性

    div的样式:[width:宽度 :100像素.height:高度100px.background:背景颜色红色] 内嵌的形式:用<style type="text/css>&l ...

  7. Red and Black---POJ - 1979

    There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A ...

  8. js生成自定义随机数方法

    function getRandom() { var chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', ...

  9. Bandwagon的配置记录(一) —— kexue上网

    写在前面 这是kexue上网的一种方法. 看文章前,先拉最底下,看一遍“写在最后”. 租个服务器 我租了个洛杉矶的服务器,系统是ubuntu16.04 x86_64 进入KiwiVM Control ...

  10. UML建模工具

    UML:Unified Modeling Language (UML)又称统一建模语言或标准建模语言,是始于1997年一个OMG标准,它是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段 ...