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. Eclipse与MyEclipse增加主题

    下载所需文件 下载地址:https://pan.baidu.com/s/1slq9lFn 如果eclipse和myeclipse里的MyEclipse 10\dropins存在features和plu ...

  2. 一个简单有效的兼容IE7浏览器的办法

    最近发现了一个简单有效的兼容IE7浏览器的办法 直接将下面代码复制道页面 <meta http-equiv="X-UA-Compatible" content="I ...

  3. synchronous interrupt and asynchronous interrupt

    Asynchronous interrupt 中斷请求信号来自CM3内核的外面,来自各种片上外设和外扩的外设,对CM3来说是"异步"的: e.g. usb otg device S ...

  4. Python学习杂记_6_字典常用操作

    字典操作 字典是由一对花括号括起来的一组“键值对”,每个键值对就是字典的一个元素,元素在字典中是无序的,常见操作如下: info = { 'name':'xiaoming', 'sex':'nan', ...

  5. strcpy_s 函数的用法

    strcpy_s和strcpy()函数的功能几乎是一样的. strcpy函数,就象gets函数一样,它没有方法来保证有效的缓冲区尺寸,所以它只能假定缓冲足够大来容纳要拷贝的字符串.在程序运行时,这将导 ...

  6. jemalloc原理分析

    netty4引入了内存池的概念,它的主要思想源自于jemalloc,由于难以理解netty中这一块的代码,我决定先看一看网上的相关文章 官方git jemalloc原理分析 jemalloc和内存管理 ...

  7. 获取应用在AppStore的地址和跳转到AppStore

    获取应用程序在App Store中的链接地址 http://itunes.apple.com/cn/app/id533655318?mt=8 把id改成自己app的id就可以了,或者在iTunes和A ...

  8. PC网页js调用本地应用程序

    最近要现实一个在PC网页中实现点击按钮调用本地应用程序的功能 其实实现原理也非常简单, 首先注册一个本地注册表文件,指向本地应用程序路径 其次在网页中用js指向这个注册表文件,就可以实现网页调用本地应 ...

  9. PyTorch 实现kmax-pooling

    max-pooling有很多种实现方式 (1)kmax-pooling import torch def kmax_pooling(x, dim, k): index = x.topk(k, dim= ...

  10. jeesite导入数据库错误:java.sql.SQLException: Incorrect string value: '\xE4\xB8\xAD\xE5\x9B\xBD' for column 'name' at row 1问题解决

    如果使用mvn antrun:run -Pinit-db进行数据库导入导致出现如下错误: 解决方法: 这个是由于新建数据库没有选择默认字符集导致的,只要选择utf-8即可.