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. PJAX的实现与应用

    一.前言 web发展经历了一个漫长的周期,最开始很多人认为Javascript这们语言是前端开发的累赘,是个鸡肋,那个时候人们还享受着从一个a链接蹦 到另一个页面的web神奇魔术.后来随着JavaSc ...

  2. 转载 什么是P问题、NP问题和NPC问题

    原文地址http://www.matrix67.com/blog/archives/105 这或许是众多OIer最大的误区之一.    你会经常看到网上出现“这怎么做,这不是NP问题吗”.“这个只有搜 ...

  3. SQL Server 2008 R2 错误代码:233

    解决方法:打开SQL Server配置管理器,找到MSSQLSERVER的协议,启动TCP/IP和Named Pipes

  4. NSSearchPathForDirectoriesInDomains函数详解

    NSSearchPathForDirectoriesInDomains函数详解     #import "NSString+FilePath.h" @implementation ...

  5. DOM0,DOM2,DOM3 事件基础知识

    事件是javascript和HTML交互基础, 任何文档或者浏览器窗口发生的交互, 都要通过绑定事件进行交互; 事件有DOM0, DOM2和DOM3的区分(别问我怎么少了一个DOM1, 也没找到DOM ...

  6. Set集合的使用

    #include<iostream> #include<set> using namespace std; typedef struct { int i,j; char s; ...

  7. C++中有关数组的相关问题

    1.数组长度相关: strlen(from <string.h>)只是针对字符数组才有的,他不包含\0的长度.无法对其他类型求长度.sizeof()则可以对\0发起作用.记住(a.leng ...

  8. Thinkphp 第二篇:如何将一个外部项目导入到Thimkphp环境中

    一:到这篇博文的开头,假设我们的Xmapp环境已经搭建好了,并且成功的安装了Thinkphp的环境了. 1:Xmapp安装成功截图: 2:Thinkphp安装成功截图: 二:Thinkphp中各个文件 ...

  9. Android M(6.0) 权限相关

    原文链接:http://jijiaxin89.com/2015/08/30/Android-s-Runtime-Permission/ Android M 新的运行时权限开发者需要知道的一切   an ...

  10. Redis Cluster 介绍与使用

    Redis Cluster 功能特性 Redis 集群是分布式的redis 实现,具有以下特性: 1. 高可用性与可线性扩张到1000个节点 2. 数据自动路由到多个节点 3. 节点间数据共享 4. ...