博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JDK源码学习笔记——LinkedHashMap
阅读量:6345 次
发布时间:2019-06-22

本文共 4129 字,大约阅读时间需要 13 分钟。

HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序。

LinkedHashMap保证了元素迭代的顺序。该迭代顺序可以是插入顺序或者是访问顺序。通过维护一个双向链表实现。

需要在理解HashMap实现原理的基础上学习LinkedHashMap,

一、数据结构

实际上就是在HashMap的基础上加了LinkedList

(图片来自)

LinkedHashMap.Entry继承了HashMap.Node,并扩展了before ,after属性

static class Entry
extends HashMap.Node
{ Entry
before, after; Entry(int hash, K key, V value, Node
next) { super(hash, key, value, next); } }

二、类

继承了HashMap

public class LinkedHashMap
extends HashMap
implements Map

 三、属性

transient LinkedHashMap.Entry
head; transient LinkedHashMap.Entry
tail; final boolean accessOrder;//true表示按照访问顺序迭代(最近访问在后),false时表示按照插入顺序(先插入在前,默认)

四、主要方法

put

/**     * 直接使用HashMap的put方法     * 重写了newNode()方法:维护双向链表     * 重写了afterNodeAccess(e)方法:如果按访问顺序排序,把node移动到双链表的尾端     */    Node
newNode(int hash, K key, V value, Node
e) { LinkedHashMap.Entry
p = new LinkedHashMap.Entry
(hash, key, value, e); linkNodeLast(p); return p; } private void linkNodeLast(LinkedHashMap.Entry
p) { LinkedHashMap.Entry
last = tail; tail = p; if (last == null) head = p; else { p.before = last; last.after = p; } } void afterNodeAccess(Node
e) { // move node to last LinkedHashMap.Entry
last; if (accessOrder && (last = tail) != e) { LinkedHashMap.Entry
p = (LinkedHashMap.Entry
)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; } }

get

/**     * 重写了get方法     * 如果按访问顺序排序,把node移动到双链表的尾端     */    public V get(Object key) {        Node
e; if ((e = getNode(hash(key), key)) == null) return null; if (accessOrder) afterNodeAccess(e);// 如果按访问顺序排序,把node移动到双链表的尾端 return e.value; }

remove

/**     * 直接使用HashMap的remove方法     * 重写了afterNodeRemoval()方法:维护双端链表     */    void afterNodeRemoval(Node
e) { // unlink LinkedHashMap.Entry
p = (LinkedHashMap.Entry
)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; }

遍历

/**     * 主要看nextNode()方法     * 直接遍历的双向链表     */    final class LinkedKeyIterator extends LinkedHashIterator implements Iterator
{ public final K next() { return nextNode().getKey(); } } final class LinkedValueIterator extends LinkedHashIterator implements Iterator
{ public final V next() { return nextNode().value; } } final class LinkedEntryIterator extends LinkedHashIterator implements Iterator
> { public final Map.Entry
next() { return nextNode(); } } abstract class LinkedHashIterator { LinkedHashMap.Entry
next; LinkedHashMap.Entry
current; int expectedModCount; LinkedHashIterator() { next = head; expectedModCount = modCount; current = null; } public final boolean hasNext() { return next != null; } final LinkedHashMap.Entry
nextNode() { LinkedHashMap.Entry
e = next; if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (e == null) throw new NoSuchElementException(); current = e; next = e.after; return e; } public final void remove() { Node
p = current; if (p == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); current = null; K key = p.key; removeNode(hash(key), key, null, false, false); expectedModCount = modCount; } }

 

 

 

 

转载于:https://www.cnblogs.com/hexinwei1/p/9723800.html

你可能感兴趣的文章
Android使用SVG矢量图打造酷炫动效!
查看>>
electron 使用 Node.js 原生模块
查看>>
iOS This app attempts to access privacy sensitive data without a usag
查看>>
Activity动画切换过程中黑屏
查看>>
vscode里面怎么根据eslint来格式化代码?
查看>>
强力学习 ES6 新语法
查看>>
加密保护软件 WinLicense常见问题整理大全(九):在运行时选择WinLicense消息的语言...
查看>>
利用Dectorator分模块存储Vuex状态(上)
查看>>
js学习之异步处理
查看>>
Vue 表情包输入组件
查看>>
hexo+github搭建个人博客
查看>>
偏向锁,轻量级锁,重量级锁
查看>>
Python学习之路40-属性描述符
查看>>
百度入链,前往何处?
查看>>
Android 开发者指南 - 性能提示
查看>>
element-ui的dropdown组件使用
查看>>
HTTP的发展历史 【积一时之跬步,臻千里之遥程】
查看>>
不要争了!技术选择没那么重要
查看>>
1 函数极限的严格定义
查看>>
内容类小程序创业的优势能为用户带来哪些新体验
查看>>