TreeMap是一颗红黑树做Map。HashMap是数组+链表+红黑树。HashTable是数组+链表。

LinkedHashMap底层存储结构与HashMap一样,不同的是LinkedHashMap增加了一个双向链表的头节点,插入的数据除了插入HashMap,还会插入链表中,因而可以保存插入节点的顺序

LinkedHashMap的节点在HashMap节点的基础上增加了前后节点的引用

LinkedHashMap相比HashMap在查找值和删除值时效率要高

LinkedHashMap还可以设置按插入顺序排序或是按访问顺序排序,默认是按插入顺序排序

LinkedHashMap没有put方法,而是覆写了afterNodeAccess方法和afterNodeInsertion方法。当插入的数据已经存在时,会调用afterNodeAccess方法看是否需要将数据插入到链表末尾;当插入的数据是新数据时,会通过afterNodeInsertion方法来根据设置删除近期使用最少的节点

LinkedHashMap可以用来实现LRU算法。首先需要用可以设置accessOrder的构造函数设置accessOrder为true,也就是按照节点访问顺序排序;

而LinkedHashMap还拥有HashMap一样的结构,原因在于其继承自HashMap,因此HashMap中用于存储元素的table也被继承过来,于是乎元素的存储也具备和HashMap一样的规则,所有元素存储在table中,table下的每个索引在原HashMap的结构下也是一个单向链表,同时每个元素中额外增加的before和after引用将table中的元素互连起来。

HashMap链表节点:next,

HashMap红黑树节点TreeNode:parent,left,right,prev,next, 

LinkedHashMap链表节点:before,after,next, 

LinkedHashMap跟HashMap一样,只不过增加了head,tail把所有元素串联起来了。

public class testLinkedHashMap1 {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
LinkedHashMap1<Integer,String> hh = new LinkedHashMap1<Integer,String>(); //链表添加
hh.put(, "");//放到LinkedHashMap1的table[0]中,此时是链表(节点有next没有after,before)
hh.put(, "");
// hh.remove(4);//链表删除
// hh.put(4, "4");
hh.put(, "");
hh.put(, "");//0位置转成红黑树
hh.put(, "");
hh.put(, "");
hh.put(, "");
hh.put(, "");//1位置链表添加
hh.put(, "");
hh.put(, ""); hh.get(); Set s = hh.keySet();//[0, 16, 32, 48, 54, 60, 76, 1, 2, 3]
Iterator i = s.iterator();
if(i.hasNext()) System.out.println(i.next());
// i.remove();
if(i.hasNext()) System.out.println(i.next()); }
}
//extends HashMap1,table也被继承过来,数组+链表+红黑树。
public class LinkedHashMap1<K, V> extends HashMap1<K, V> implements Map1<K, V> {
private static final long serialVersionUID = 3801124242820219131L;
transient LinkedHashMap1.Entry<K, V> head;// 双向链表的头节点和尾节点
transient LinkedHashMap1.Entry<K, V> tail;
final boolean accessOrder;// true,使用节点之后就把节点放到最末尾。false就不放。用于删除第一个最不常用的元素。 private void linkNodeLast(LinkedHashMap1.Entry<K, V> p) {// 链表末尾添加,有before,after
LinkedHashMap1.Entry<K, V> last = tail;//保留原来的tail
tail = p;//修改tail
if (last == null)// tail=null
head = p;// tail = head = p
else {
p.before = last;
last.after = p;
}
} // dst替换src
private void transferLinks(LinkedHashMap1.Entry<K, V> src, LinkedHashMap1.Entry<K, V> dst) {
LinkedHashMap1.Entry<K, V> b = dst.before = src.before;
LinkedHashMap1.Entry<K, V> a = dst.after = src.after;
if (b == null)// 替换的src是第一个节点
head = dst;
else
b.after = dst;
if (a == null)// 替换的src是最后一个节点
tail = dst;
else
a.before = dst;
} public void reinitialize() {
super.reinitialize();// table = null; entrySet = null; keySet = null; values = null;
head = tail = null;
}
//生成一个节点(链表中的节点,不是红黑树中的节点,有hash, key, value, next没有before,after)
public Node<K, V> newNode(int hash, K key, V value, Node<K, V> e) {//
LinkedHashMap1.Entry<K, V> p = new LinkedHashMap1.Entry<K, V>(hash, key, value, e);
linkNodeLast(p);// 生成新的节点并插入到尾部
return p;
} public Node<K, V> replacementNode(Node<K, V> p, Node<K, V> next) {
LinkedHashMap1.Entry<K, V> q = (LinkedHashMap1.Entry<K, V>) p;
LinkedHashMap1.Entry<K, V> t = new LinkedHashMap1.Entry<K, V>(q.hash, q.key, q.value, next);
transferLinks(q, t);// t替换q
return t;
} public 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);// 末尾添加p
return p;
} public TreeNode<K, V> replacementTreeNode(Node<K, V> p, Node<K, V> next) {
LinkedHashMap1.Entry<K, V> q = (LinkedHashMap1.Entry<K, V>) p;
TreeNode<K, V> t = new TreeNode<K, V>(q.hash, q.key, q.value, next);
transferLinks(q, t);// t替换q
return t;
} public void afterNodeRemoval(Node<K, V> e) { // 删除节点e
LinkedHashMap1.Entry<K, V> p = (LinkedHashMap1.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;
} public void afterNodeInsertion(boolean evict) { // 添加新的节点时候,有可能删除最老的元素
LinkedHashMap1.Entry<K, V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;// 删除第一个元素,每次使用元素之后,就会把元素放到最末尾,第一个元素就是最少使用的元素。
removeNode(hash(key), key, null, false, true);// hashMap方法,
}
} public void afterNodeAccess(Node<K, V> e) { // 节点e被修改后,e不是尾节点(e是尾节点就不动),把e节点移到最后。
LinkedHashMap1.Entry<K, V> last;
if (accessOrder && (last = tail) != e) {
LinkedHashMap1.Entry<K, V> p = (LinkedHashMap1.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;
}
} public void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after) {
s.writeObject(e.key);
s.writeObject(e.value);
}
} public LinkedHashMap1(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
accessOrder = false;// true,使用节点之后就把节点放到最末尾。false就不放。
} public LinkedHashMap1(int initialCapacity) {
super(initialCapacity);// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
accessOrder = false;
} public LinkedHashMap1() {
super();// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
accessOrder = false;
} public LinkedHashMap1(Map1<? extends K, ? extends V> m) {
super();// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
accessOrder = false;
putMapEntries(m, false);
} public LinkedHashMap1(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor);// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
this.accessOrder = accessOrder;
} public boolean containsValue(Object value) {
for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after) {
V v = e.value;
if (v == value || (value != null && value.equals(v)))
return true;
}
return false;
} public V get(Object key) {
Node<K, V> e;
if ((e = getNode(hash(key), key)) == null)// hashMap方法
return null;
if (accessOrder)
afterNodeAccess(e);// 把e节点移到最后。
return e.value;
} public V getOrDefault(Object key, V defaultValue) {
Node<K, V> e;
if ((e = getNode(hash(key), key)) == null)// hashMap方法
return defaultValue;
if (accessOrder)// 把e节点移到最后。
afterNodeAccess(e);
return e.value;
} public void clear() {
super.clear();
head = tail = null;
} // 添加一个元素时候是否删除最老的。 map是缓存有用。比如到达100之后,添加一个元素就删除最老的元素。要重写。
protected boolean removeEldestEntry(Map1.Entry<K, V> eldest) {
return false;
} public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new LinkedKeySet();
keySet = ks;
}
return ks;
} final class LinkedKeySet extends AbstractSet<K> {
public final int size() {
return size;
} public final void clear() {
LinkedHashMap1.this.clear();
} public final Iterator<K> iterator() {
return new LinkedKeyIterator();
} public final boolean contains(Object o) {
return containsKey(o);
} public final boolean remove(Object key) {
return removeNode(hash(key), key, null, false, true) != null;// hashMap方法
} public final Spliterator<K> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT);
} public final void forEach(Consumer<? super K> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
action.accept(e.key);
if (modCount != mc)
throw new ConcurrentModificationException();
}
} public Collection<V> values() {
Collection<V> vs = values;
if (vs == null) {
vs = new LinkedValues();
values = vs;
}
return vs;
} final class LinkedValues extends AbstractCollection<V> {
public final int size() {
return size;
} public final void clear() {
LinkedHashMap1.this.clear();
} public final Iterator<V> iterator() {
return new LinkedValueIterator();
} public final boolean contains(Object o) {
return containsValue(o);
} public final Spliterator<V> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED);
} public final void forEach(Consumer<? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
action.accept(e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
} public Set<Map1.Entry<K, V>> entrySet() {
Set<Map1.Entry<K, V>> es;
return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
} final class LinkedEntrySet extends AbstractSet<Map1.Entry<K, V>> {
public final int size() {
return size;
} public final void clear() {
LinkedHashMap1.this.clear();
} public final Iterator<Map1.Entry<K, V>> iterator() {
return new LinkedEntryIterator();
} public final boolean contains(Object o) {
if (!(o instanceof Map1.Entry))
return false;
Map1.Entry<?, ?> e = (Map1.Entry<?, ?>) o;
Object key = e.getKey();
Node<K, V> candidate = getNode(hash(key), key);// hashMap方法
return candidate != null && candidate.equals(e);
} public final boolean remove(Object o) {
if (o instanceof Map1.Entry) {
Map1.Entry<?, ?> e = (Map1.Entry<?, ?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;// hashMap方法
}
return false;
} public final Spliterator<Map1.Entry<K, V>> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT);
} public final void forEach(Consumer<? super Map1.Entry<K, V>> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
action.accept(e);
if (modCount != mc)
throw new ConcurrentModificationException();
}
} public void forEach(BiConsumer<? super K, ? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
action.accept(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
} public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
if (function == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
e.value = function.apply(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
} public static class Entry<K, V> extends HashMap1.Node<K, V> {
public Entry<K, V> before, after;// hash, key, value, next public Entry(int hash, K key, V value, Node<K, V> next) {
super(hash, key, value, next);// before和after引用节点以支持双向链表
}
} abstract class LinkedHashIterator {//头结点head开始一路after到末尾
LinkedHashMap1.Entry<K, V> next;
LinkedHashMap1.Entry<K, V> current;
int expectedModCount; LinkedHashIterator() {
next = head;// 初始化时下一个是head
expectedModCount = modCount;
current = null;
} public final boolean hasNext() {
return next != null;
} final LinkedHashMap1.Entry<K, V> nextNode() {
LinkedHashMap1.Entry<K, V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
current = e;
next = e.after;// before和after遍历链表
return e;
} public final void remove() {
Node<K, V> 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);// hashMap方法
expectedModCount = modCount;
}
} final class LinkedKeyIterator extends LinkedHashIterator implements Iterator<K> {
public final K next() {
return nextNode().getKey();
}
} final class LinkedValueIterator extends LinkedHashIterator implements Iterator<V> {
public final V next() {
return nextNode().value;
}
} final class LinkedEntryIterator extends LinkedHashIterator implements Iterator<Map1.Entry<K, V>> {
public final Map1.Entry<K, V> next() {
return nextNode();
}
} }

LinkedHashMap源码的更多相关文章

  1. 转:【Java集合源码剖析】LinkedHashmap源码剖析

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/37867985   前言:有网友建议分析下LinkedHashMap的源码,于是花了一晚上时 ...

  2. Java集合系列[4]----LinkedHashMap源码分析

    这篇文章我们开始分析LinkedHashMap的源码,LinkedHashMap继承了HashMap,也就是说LinkedHashMap是在HashMap的基础上扩展而来的,因此在看LinkedHas ...

  3. linkedHashMap源码解析(JDK1.8)

    引言 关于java中的不常见模块,让我一下子想我也想不出来,所以我希望以后每次遇到的时候我就加一篇.上次有人建议我写全所有常用的Map,所以我研究了一晚上LinkedHashMap,把自己感悟到的解释 ...

  4. LRU算法实现,HashMap与LinkedHashMap源码的部分总结

    关于HashMap与LinkedHashMap源码的一些总结 JDK1.8之后的HashMap底层结构中,在数组(Node<K,V> table)长度大于64的时候且链表(依然是Node) ...

  5. LinkedHashMap源码详解

    序言 本来是不打算先讲map的,但是随着对set集合的认识,发现如果不先搞懂各种map,是无法理解set的.因为set集合很多的底层就是用map来存储的.比如HashSet就是用HashMap,Lin ...

  6. 给jdk写注释系列之jdk1.6容器(5)-LinkedHashMap源码解析

    前面分析了HashMap的实现,我们知道其底层数据存储是一个hash表(数组+单向链表).接下来我们看一下另一个LinkedHashMap,它是HashMap的一个子类,他在HashMap的基础上维持 ...

  7. LinkedHashMap 源码详细分析(JDK1.8)

    1. 概述 LinkedHashMap 继承自 HashMap,在 HashMap 基础上,通过维护一条双向链表,解决了 HashMap 不能随时保持遍历顺序和插入顺序一致的问题.除此之外,Linke ...

  8. LinkedHashMap源码分析

    hashMap源码分析:hashMap源码分析 版本说明:jdk1.7LinkedHashMap继承于HashMap,是一个有序的Map接口的实现.有序指的是元素可以按照一定的顺序排列,比如元素的插入 ...

  9. LinkedHashMap源码分析及实现LRU

    概述 从名字上看LinkedHashMap相比于HashMap,显然多了链表的实现.从功能上看,LinkedHashMap有序,HashMap无序.这里的顺序指的是添加顺序或者访问顺序. 基本使用 @ ...

  10. 死磕 java集合之LinkedHashMap源码分析

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 LinkedHashMap内部维护了一个双向链表,能保证元素按插入的顺序访问,也能以访问 ...

随机推荐

  1. from import语句

    *)假如导入出现了问题,那么一定是导入的文件里的语法问题或者其他问题 参考链接:http://www.cnblogs.com/hwf-73/p/5493328.html 1)导入时重命名 as fro ...

  2. bugku——宽带信息泄露(RouterPassView 查看路由器配置信息)

    题目地址:http://ctf.bugku.com/files/5986768ca8b96cead45aec16a88431b5/conf.bin 下载之后发现是个后缀名为bin的二进制文件,其实这个 ...

  3. 英语chiltonite葡萄石chiltonite单词

    葡萄石Chiltonite 1.葡萄石能够促进血液循环,具有美容养颜的功效,非常适合女性佩戴,可以增加个人魅力,还能加强事业财运,凝聚财富气场. 2.绿色光对应人体心轮,对心脏,肺脏有效用,内涵的磁石 ...

  4. android studio学习----通过gradle来导入jar包

    转载地址:http://www.th7.cn/Program/Android/201507/495477.shtml File->Project Structure 可以打开下面的图: 1.通过 ...

  5. Linux shell awk模式使用

    awk的PATTERN表示方法: 1,正则表达式,格式为/regex/ 以冒号为分隔符,显示/etc/passwd以r开头的行的第一段 [root@wei awk]# awk -F: '/^r/{pr ...

  6. ChengDu University Mental Health Test 需求分析文档

    ChengDu University Mental Health Website 需求分析文档 V4.0 编制人:刘雷,黄凯 日期:2019/4/28 版本修订历史记录: 版本 日期 修改内容 作者 ...

  7. Colorimetry

    [Colorimetry] 1.Example of Spectral Power Distribution Application An example of the spectral power ...

  8. React源码 memo Fragment StrictMode cloneElement createFactory

    1.memo react 16.6 推出的 api ,他的用意是给 function component 也有 PureComponent 这样一个类似的功能,因为我们知道 PureComponent ...

  9. POJ 2516Minimum Cost(最小费用流+特判)

    [题意]: 有N个人,M个仓库,每个人需要物品,个数都等于共同的K,仓库中有对应的K件物品的数量,随后给K个N*M矩阵(小写k, n, m表示K,N,M对应的子集),表明m个仓库到第n个人的位置运送k ...

  10. node 单线程异步非阻塞

    链接:http://www.runoob.com/nodejs/nodejs-callback.html 首先什么是单线程异步非阻塞? 单线程的意思整个程序从头到尾但是运用一个线程,程序是从上往下执行 ...