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. poj 2528 Mayor's posters 线段树 || 并查集 离线处理

    题目链接 题意 用不同颜色的线段覆盖数轴,问最终数轴上有多少种颜色? 注:只有最上面的线段能够被看到:即,如果有一条线段被其他的线段给完全覆盖住,则这个颜色是看不到的. 法一:线段树 按题意按顺序模拟 ...

  2. UBUNTU命令行下进程查看-终止

    ps ax   显示当前系统进程的列表 ps aux 显示当前系统进程详细列表以及进程用户 如果输出过长,可能添加管道命令 less  如  ps ax|less 查看具体进程,使用 grep命令如  ...

  3. Codeforces Gym100971 L.Chess Match (IX Samara Regional Intercollegiate Programming Contest Russia, Samara, March 13)

    这个题就是两个队,看最多能赢的个数,然后比较一下,看两个队是都能赢彼此,还是只有一个队赢的可能性最大.表达能力不好,意思差不多... 和田忌赛马有点像,emnnn,嗯. 代码: 1 #include& ...

  4. 10.1综合强化刷题 Day6

    T1 排序 题目描述 小Z 有一个数字序列a1; a2; .... ; an,长度为n,小Z 只有一个操作:选 定p(1<p<n),然后把ap 从序列中拿出,然后再插⼊到序列中任意位置. ...

  5. Java原子操作类,你知道多少?

    原子操作类简介 由于synchronized是采用的是悲观锁策略,并不是特别高效的一种解决方案. 实际上,在J.U.C下的atomic包提供了一系列的操作简单,性能高效,并能保证线程安全的类去 更新基 ...

  6. 百度前端开发规范 by fex-team

    github:https://github.com/fex-team/styleguide 离线版本: 链接:http://pan.baidu.com/s/1gfr857l 密码:cvk3 注:只支持 ...

  7. 创建maven项目是其中的group id和artifact id怎么填写

    groupid和artifactId被统称为“坐标”是为了保证项目唯一性而提出的,如果你要把你项目弄到maven本地仓库去,你想要找到你的项目就必须根据这两个id去查找. groupId一般分为多个段 ...

  8. iOS 5的文件存储策略应对

    苹果在iOS 5系统时,对app的文件存储提出了新的要求.从它的guildline来看,是推荐开发者尽量把app生成的文件放在Caches目录下的.原文如下: Only user-generated ...

  9. 鼠标悬浮弹出标题制作JQuery

    今天给客户制作的网站里面加个效果,当鼠标在列表图片之外时,标题不显示,当鼠标悬浮在图片之上时,标题从底部弹出. 效果图如下: 鼠标悬浮前: 鼠标悬浮后: html代码如下: <ul class= ...

  10. 【温故知新】——HTML5重要知识点复习

    前言:本文是自己在学习课程中的课程笔记,这里用来温故知新的,并非本人原创. 一.HTML5新特性 —— 十个新特性:凌乱 (1)新的语义标签 (2)增强型表单(表单2.0) (3)音频和视频 (4)C ...