Java源代码之LinkedHashMap

转载请注明出处:http://blog.csdn.net/itismelzp/article/details/50554412

一、LinkedHashMap概述

LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序

此实现与
HashMap 的不同之处在于,LinkedHashMap维护着一个执行于全部条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。

注意,假设在映射中又一次插入键,则插入顺序不受影响。(假设在调用 m.put(k, v) 前 m.containsKey(k) 返回了 true。则调用时会将键 k 又一次插入到映射 m 中。

注意。此实现不是同步的。假设多个线程同一时候訪问链接的哈希映射,而当中至少一个线程从结构上改动了该映射,则它必须 保持外部同步。

这一般通过对自然封装该映射的对象进行同步操作来完毕。

假设不存在这种对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。

二、数据结构

数组 + 双链表结构

/**
* 双链表结点Entry,继承自HashMap.Node
*/
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);
}
}

三、LinkedHashMap源代码

1.头文件

package java.util;

import java.util.function.Consumer;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.io.IOException;

2.继承与实现关系

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

3.属性

/**
* 双链表的头结点
*/
transient LinkedHashMap.Entry<K,V> head; /**
* 双链表的尾结点
*/
transient LinkedHashMap.Entry<K,V> tail; /**
* 迭代顺序
* true:訪问顺序
* false:插入顺序
*/
final boolean accessOrder;

4.构造方法

/**
* 构造方法一:
* 指定初始容量和装载因子
* 顺序规则:插入顺序
*/
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
} /**
* 构造方法二:
* 指定初始容量并使用默认装载因子(0.75)
* 顺序规则:插入顺序
*/
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
} /**
* 构造方法三:
* 使用默认初始容量(16)和默认装载因子(0.75)
* 顺序规则:插入顺序
*/
public LinkedHashMap() {
super();
accessOrder = false;
} /**
* 构造方法四:
* 使用指定Map来构造
* 顺序规则:插入顺序
*/
public LinkedHashMap(Map<? extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
} /**
* 构造方法五:
* 指定初始容量、装载因子和顺序规则构造
*
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}

5.方法

(1) 存储数据

LinkedListHashMap并未重写HashMap中的put方法。

详细实现可參考Java源代码之HashMap】中put与putValue方法。

(2) 读取数据

/**
* 假设key存在返回相应的value
* 假设key不存在返回指定的null
*/
public V get(Object key) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
} /**
* 假设key存在返回相应的value
* 假设key不存在返回指定的defaultValue
*/
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) == null)
return defaultValue;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}

6.迭代

集合中的类都有一个共同的迭代方式,就是先把这个集合转化成Set视图,然后再对这个Set视图进行迭代。

/**
* 返回一个包括此Map全部元素的Set视图(实际是LinkedEntrySet类)
* 改变Map也会改变视图
*/
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
} /**
* 内部类LinkedEntrySet
* 里面封闭了迭代方法
*/
final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator<Map.Entry<K,V>> iterator() {
return new LinkedEntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Node<K,V> candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e);
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;
}
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED |
Spliterator.DISTINCT);
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
action.accept(e);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}

Java源代码之LinkedHashMap的更多相关文章

  1. 分治法解决合并排序(c++和Java源代码)

    Java源代码 public class Mergesort1 { public static void merge(int[]a,int low,int mid,int high){//对两组已经排 ...

  2. java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器

    java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器 下载地址:http://yunpan.cn/QXhEcGNYLgwTD 运行方式:java -jar Encryp ...

  3. 全中国的省市县镇乡村数据获取以及展示java源代码

    第一步.准备工作(数据源+工具): 数据源(截止目前最全面权威的官方数据):http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/ 爬取数据的工具 ...

  4. PowerDesigner(八)-面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)(转)

    面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...

  5. Android APK反编译得到Java源代码和资源文件

    在此郑重声明,贴出来的目的不是为了去破解人家的软件,完全是一种学习的态度,不过好像通过这种方式也可以去汉化一些外国软件. 一.反编译Apk得到Java源代码 首先要下载两个工具:dex2jar和JD- ...

  6. MyEclipse13中修改Servlet.java源代码

    Servlet.java源代码想要修改的步骤,与低版本的不同废话少说,直接来步骤: 1,在myEclipse的安装目录中搜索com.genuitec.eclipse.wizards文件,如图:选择co ...

  7. 看java源代码

    不会看JDK源代码,相当于没学过Java. 网上不容易找到一篇帮助我解决了如何在Eclipse下查看JDK源代码 的文章. 核心提示:在Eclipse中查看JDK类库的源代码!!! 设置: 1.点 w ...

  8. 混淆器:java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器

    java程序保护如何知识产权,特别提供一个java 开发的java 源代码级的混淆器 下载地址:http://yunpan.cn/QXhEcGNYLgwTD 运行方式:java -jar Encryp ...

  9. [注意事项&amp;车轮]java源代码 产生局部javadoc api档

    随着Eclipse书写java码时间,有时候,因为我们不知道java函数返回.通过鼠标移动到java该功能,假设它javadoc相关内容将被显示. 但是,并非所有java代码javadoc:连装jav ...

随机推荐

  1. AVRStudio 6 设置F_CPU时钟频率

    具体如下: 1>右键项目属性 2>根据语言选择一下,C或C++

  2. android基本控件学习-----Button

    Button讲解: 一.在我们实际的使用button的时候经常会对button不同状态会有不同的显示,在讲解Button前,首先对drawable下面的statelistdrawable的相关知识讲一 ...

  3. netbean下搭建mariadb数据库

    本人的操作系统Manjaro 最新版,mariadb版本为10.1.1,使用netbeasn开发java WEB,搭建过程如下: 1.安装数据库 pacman -S mariadb 2.启动数据库服务 ...

  4. windows下安装oracle,sqlplus连接启动oracle(oracle 主机字符串输入是什么)

    1.oracle安装 参考http://wenku.baidu.com/view/d01ffd43336c1eb91a375d68.html,这里不再赘述 2.命令行sqlplus连接oracle   ...

  5. AC日记——[Sdoi2016]数字配对 bzoj 4514

    4514 思路: 很受伤现在,,测了那么多次不过的原因就是因为INF不够大: 解法有两种: 解法1: 把n个点按照质因数个数为奇或偶分为两个点集(很容易就可以想到): 然后,按照题目连边跑最大费用流: ...

  6. react 使用antd导航组件实现事件传递并局部刷新DOM

    我们要实现一个通过点击顶部导航来查询左侧菜单的一个功能 在这个功能中,我们要应用到onClick={this.headNavMenuList.bind(this)}方法来传递点击 不同按钮来传递不同的 ...

  7. JavaScript的Object

    题目 var foo = new Object(); var bar = new Object(); var map = new Object(); map[foo] = "foo" ...

  8. 2016北京集训测试赛(十四)Problem A: 股神小L

    Solution 考虑怎么卖最赚钱: 肯定是只卖不买啊(笑) 虽然说上面的想法很扯淡, 但它确实能给我们提供一种思路, 我们能不买就不买; 要买的时候就买最便宜的. 我们用一个优先队列来维护股票的价格 ...

  9. Data structure basics - Java Implementation

    Stack & Queue Implementations FixedCapacityQueue package cn.edu.tsinghua.stat.mid_term; import j ...

  10. Maven出现错误No plugin found for prefix 'jetty' in the current project and in the plugin groups的问题解决

    只需在maven的setting.xml文件上加入如下节点: <pluginGroups> <pluginGroup>org.mortbay.jetty</pluginG ...