LinkedHashMap是HashMap的子类,很多地方都是直接引用HashMap中的方法,所以需要注意的地方并不多。关键的点就是几个重写的方法:

1、Entry是继承与Node类,也就是LinkedHashMap与HashMap的根本区别所在,Node是链表形式,只有next与下一个元素进行连接,而Entry的链表有before和after两个连接点。

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);
}
}

2、区别是将节点变成Entry,并且按照链表方式将元素有序连接

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;
}

3、红黑树节点类型并没有改变,也只是按照链表方式连接

TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next);
linkNodeLast(p);
return p;
}
HashMap中为LinkedHashMap留下了三个预留方法:
1、第一个比较好理解,在删除元素e的时候将e前后的元素相连。
void afterNodeRemoval(Node<K,V> e) { // unlink
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.before = p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a == null)
tail = b;
else
a.before = b;
}

2、这个方法表面上看是判断是否删除链表中第一个元素,但是实际上是为重写LRU而准备的。

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);
}
}
关键就是下面这个方法,在LinkedHashMap中默认返回是false,当需要实现LRU算法的时候继承LinkedHashMap的子类重写这个方法即可,LRU内容较多,稍后会单开一贴记录。
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
3、第三个方法主要是将元素移到链表的最后一位,关键参数是accessOrder,这个参数只有在public LinkedHashMap(int initialCapacity, float loadFactor,boolean accessOrder) 中可以手动设置为true,其余时候都默认为false,所以这个方法实际用到的地方比较少。
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;
}
}
accessOrder这个参数的实际意义是控制链表get的时候是按照插入顺序还是访问顺序,比如下面的例子:

 Map<String,String> m = new LinkedHashMap(16,0.75F,true);
m.put("1", "a");
m.put("2", "b");
m.put("3", "c");
m.put("4", "d");
m.get("1");
m.get("2");
m.forEach((x,y)->{System.out.println(y);});
这时的输出是cdab,如果accessOrder设置为false则输出abcd。
 
这种链表形式其实在调用get方法的时候没有什么差别,存储方式也没有什么差别,差别在于forEach这个方法。HashMap中想要遍历所有元素只能通过三种set集合的迭代器,但是LinkedHashMap自身实现了forEach方法,而且在put的时候队元素进行了排序,所以可以直接对自身进行遍历。

LinkedHashMap源码阅读笔记(基于jdk1.8)的更多相关文章

  1. ArrayList源码阅读笔记(基于JDk1.8)

    关键常量: private static final int DEFAULT_CAPACITY = 10; 当没有其他参数影响数组大小时的默认数组大小 private static final Obj ...

  2. JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

    JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...

  3. jdk源码阅读笔记-LinkedHashMap

    Map是Java collection framework 中重要的组成部分,特别是HashMap是在我们在日常的开发的过程中使用的最多的一个集合.但是遗憾的是,存放在HashMap中元素都是无序的, ...

  4. JDK1.8源码阅读笔记(1)Object类

    JDK1.8源码阅读笔记(1)Object类 ​ Object 类属于 java.lang 包,此包下的所有类在使⽤时⽆需⼿动导⼊,系统会在程序编译期间⾃动 导⼊.Object 类是所有类的基类,当⼀ ...

  5. gogs 源码阅读笔记 001

    gogs 源码阅读笔记 001 gogs项目相当不错,本笔记实际是基于gogs fork版本 git-122a66f. gitea (gitea版本由来)[https://blog.gitea.io/ ...

  6. faster rcnn源码阅读笔记1

    自己保存的源码阅读笔记哈 faster rcnn 的主要识别过程(粗略) (开始填坑了): 一张3通道,1600*1600图像输入中,经过特征提取网络,得到100*100*512的feature ma ...

  7. HashMap源码阅读笔记

    HashMap源码阅读笔记 本文在此博客的内容上进行了部分修改,旨在加深笔者对HashMap的理解,暂不讨论红黑树相关逻辑 概述   HashMap作为经常使用到的类,大多时候都是只知道大概原理,比如 ...

  8. guavacache源码阅读笔记

    guavacache源码阅读笔记 官方文档: https://github.com/google/guava/wiki/CachesExplained 中文版: https://www.jianshu ...

  9. CI框架源码阅读笔记5 基准测试 BenchMark.php

    上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...

随机推荐

  1. 常用function() 收集

    1.随机数生成函数(来源-微信支付demo案例) /** * * 产生随机字符串,不长于32位 * @param int $length * @return 产生的随机字符串 */ public st ...

  2. js像素运算问题

    通过DOM获取的某一距离属性(比如left)是带px单位的,直接对其算术运算不起效,要先把获取到的值处理一下去掉px单位. 方法一(用处理字符串的方式去除px): var x=document.get ...

  3. R语言——绘制半圆形图

    好久没发点新的作品了.......也许...... Que sera, seraWhatever will be, will be

  4. 【转载】--仅用 []()+! 就足以实现几乎任意Javascript代码

    最近在做CTF的题目,遇见了一个都是[]()+!这样的文件,于是百度了一下,发现这个博客对这个有解释. G Reader里Dexter同学的分享,来自sla.ckers.org的又一神作 点我测试 G ...

  5. Ubuntu14.04 lamp环境 php mongodb扩展安装

    安装pecl支持: sudo apt-get install php5-dev php5-cli php-pear 安装mongo驱动 sudo pecl install mongo 修改php.in ...

  6. JSP学习网站

    JSP学习网站 http://www.yiibai.com/jstl/ http://www.w3cschool.cc/jsp/jsp-jstl.html

  7. scrapy 学习笔记

    1.scrapy 配合 selenium.phantomJS 抓取动态页面, 单纯的selemium 加 Firefox浏览器就可以抓取动态页面了, 但开启窗口太耗资源,而且一般服务器的linux 没 ...

  8. 修改html页面文字选中样式

    ::selection { background-color: #31B0D5; color: #fff; text-shadow: 0 1px 0 rgba(0,0,0,.2); }

  9. Mysql安装及主从复制配置

    1.下载 mysql数据库 wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.9-linux-glibc2.5-x86_64.ta ...

  10. Android 常用开发工具以及Mac常用软件

    Android 常用的开发工具记录.其中包括AndroidStudio(IDEA)插件.Mac 上好用的软件以及国内知名Android开发者博客等. Android Studio 插件 codota ...