1、简述

    LinkedHashMap是HashMap的子类,他们最大的不同是,HashMap内部维护的是一个单向的链表数组,而LinkedHashMap内部维护的是一个双向的链表数组。HashMap是无序的,LinkedHashMap可以根据访问顺序或者插入顺序进行排序(默认是根据插入顺序的,当设置accessOrder为true时会按照访问顺序排序),当按照访问顺序排序的时候,每次get或put操作时,都会将该节点放到链表的末尾

2、实现

  1、数据结构:

    LinkedHashMap是HashMap的子类,它的内部同样是使用了hashMap定义的链表数组存储的数据。只不过在HashMap中使用的是单想链表Node<k,v>作为每个节点,而LinkedHashMap使用了集成了HashMap.Node<k,v>的双向链表Entry<k,v>来作为每个节点,Entry<k,v>在Node<k,v>的基础上增加了Entry<K,V> before, after两个属性,将数组中的前后元素关联起来,这样的实现也为LinkedHashMap根据插入顺序或访问顺序提供了可能

  2、构造方法:

    LinkedHashMap是HashMap的子类,它提供了五种构造方法,

 public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap() {
super();
accessOrder = false;
}
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;
}

    从以上我们可以看出,前面四中构造方法都是默认的accessOrder=false,即按找插入顺序排序,第五种构造方法我们可以自己定义accessOrder的值,当为true时,说明是按照访问顺序排序的,每次put或get操作的时候都会将元素移到链表的末尾

  3、LinkedHashMap操作

      由于LinkedHashMap继承了HashMap类,而且并没有重写put,get等方法,所以在这里对于LinkedHashMap的基础操作的源码就不再分析,感兴趣的可以参考上一篇关于HashMap的学习笔记。在这里重点看一下LinkedHashMap提供的removeEldestEntry(Map.Entry<K,V> eldest)方法

    

/**
* Returns <tt>true</tt> if this map should remove its eldest entry.
* This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
* inserting a new entry into the map. It provides the implementor
* with the opportunity to remove the eldest entry each time a new one
* is added. This is useful if the map represents a cache: it allows
* the map to reduce memory consumption by deleting stale entries.
*
* <p>Sample use: this override will allow the map to grow up to 100
* entries and then delete the eldest entry each time a new entry is
* added, maintaining a steady state of 100 entries.
* <pre>
* private static final int MAX_ENTRIES = 100;
*
* protected boolean removeEldestEntry(Map.Entry eldest) {
* return size() &gt; MAX_ENTRIES;
* }
* </pre>
*
* <p>This method typically does not modify the map in any way,
* instead allowing the map to modify itself as directed by its
* return value. It <i>is</i> permitted for this method to modify
* the map directly, but if it does so, it <i>must</i> return
* <tt>false</tt> (indicating that the map should not attempt any
* further modification). The effects of returning <tt>true</tt>
* after modifying the map from within this method are unspecified.
*
* <p>This implementation merely returns <tt>false</tt> (so that this
* map acts like a normal map - the eldest element is never removed).
*
* @param eldest The least recently inserted entry in the map, or if
* this is an access-ordered map, the least recently accessed
* entry. This is the entry that will be removed it this
* method returns <tt>true</tt>. If the map was empty prior
* to the <tt>put</tt> or <tt>putAll</tt> invocation resulting
* in this invocation, this will be the entry that was just
* inserted; in other words, if the map contains a single
* entry, the eldest entry is also the newest.
* @return <tt>true</tt> if the eldest entry should be removed
* from the map; <tt>false</tt> if it should be retained.
*/
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}

    这个方法就是判断是否需要删除LinkedHashMap中最旧的元素,默认是false的。当我们需要利用hashmap做一些数据的缓存,可能有的数据是使用了一两次之后就失去了价值,此外我们也不想看到缓存的map无限的增长又不想自己手动的去维护这个map。此时我们就可以使用LinkedHashMap来完成这个功能;

public class Demo {
static class MyMap<k,v> extends LinkedHashMap<k,v>{ //定义一个继承LinkedHashMap的类,并重写removeEldestEntry方法
int size;
public MyMap (int size){ //只提供一个有参的构造方法,用来设置map的大小
/*
* 这里调用的是LinkedHashMap的LinkedHashMap(int initialCapacity,boolean accessOrder)
* 构造方法,设置按访问顺序排序
*/
super(16,0.75f,true);
this.size = size;
}
@Override
protected boolean removeEldestEntry(Entry<k, v> eldest) {
// TODO Auto-generated method stub
return this.size<size(); //设置当map里面存放的元素超过MyMap设置的size时就删除最老的元素
} }
public static void main(String[] args) {
Map<String,String> map = new MyMap<String,String>(5);
for (int i = 0; i < 10; i++) {
map.put(i+"", i+"");
System.out.print(i+"="+map.size()+"\t");
}
System.out.println();
//遍历map看看里面的元素
map.forEach((k,v)->{
System.out.println("k="+k);
}); //此时访问一下里面的元素,再观察遍历后的顺序
map.get("6");map.get("8");
System.out.println("========================");
map.forEach((k,v)->{
System.out.println("k="+k);
});
}
} 打印的结果:
  

0=1 1=2 2=3 3=4 4=5 5=5 6=5 7=5 8=5 9=5
k=5
k=6
k=7
k=8
k=9
========================
k=5
k=7
k=9
k=6
k=8

 

  

总结:

    在学完LinkedHashMap和HashMap之后我们会发现,这两种集合类是非常相似的,二者都是通过内部数组去保存数据的,不同的是HashMap数组中的每个元素都是一个单向的链表,指向了产生hash冲突时和它本身具有相同hash值的元素,所以HashMap只能是无序的。LinkedHashMap中数组里面的每一个元素都是一个双向链表,它不仅指向了产生hash冲突时下一个跟它本身具有相同hash值的位置,还指定了它的上一个和下一个元素(可以是插入顺序的上一个下一个,也可以试访问顺序的上一个下一个),这样为LinkedHashMap实现有序提供了可能

java集合类学习笔记之LinkedHashMap的更多相关文章

  1. java集合类学习笔记之HashMap

    1.简述 HashMap是java语言中非常典型的数据结构,也是我们平常用的最多的的集合类之一.它的底层是通过一个单向链表(Node<k,v>)数组(也称之为桶bucket,数组的长度也叫 ...

  2. java集合类学习笔记之ArrayList

    1.简述 ArrayList底层的实现是使用了数组保存所有的数据,所有的操作本质上是对数组的操作,每一个ArrayList实例都有一个默认的容量(数组的大小,默认是10),随着 对ArrayList不 ...

  3. Java集合类学习笔记2

    二,具体的集合 集合类型 描述 ArrayList 一种可以动态增长和缩减的索引序列 LinkedList 一种可以在任何位置进行高效地插入和删除操作的有序序列 ArrayDeque 一种用循环数组实 ...

  4. java集合类学习笔记1

    一.集合的接口 java集合类库也将接口与实现相分离.首先看一下大家都熟悉的数据结构-队列是如何分离的.队列接口指出可以在队列的尾部添加元素,在队列的头部删除元素,并且可以查找队列中元素的个数.当需要 ...

  5. Java集合类学习笔记(各种Map实现类的性能分析)

    HashMap和Hashtable的实现机制几乎一样,但由于Hashtable是一个古老的.线程安全的集合,因此HashMap通常比Hashtable要快. TreeMap比HashMap和Hasht ...

  6. Java集合类学习笔记(Map集合)

    Map用于保存具有映射关系的数据,因此Map集合里保存着两组数据,一组用于保存Map的key,一组用于保存key所对应的value. Map的key不允许重复. HashMap和Hashtable都是 ...

  7. Java集合类学习笔记(Set集合)

    Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入. HashSet类的特点: 不能保证元素的排列顺序,顺 ...

  8. Java集合类学习笔记(各种线性表性能分析)

    ArrayList.LinkedList是线性表的两种典型实现:基于数组的线性表和基于链的线性表. Queue代表了队列,Deque代表了双端队列. 一般来说,由于数组以一块连续内存区来保存所有的数组 ...

  9. Java集合类学习笔记(Queue集合)

    Queue集合用于模拟队列(先进先出:FIFO)这种数据类型. Queue有一个Deque接口,代表一个"双端队列",双端队列可以同时从两端来添加.删除元素,因此Deque的实现类 ...

随机推荐

  1. 如何了解一个Web项目

    一:学会如何读一个JavaWeb项目源代码 步骤:表结构->web.xml->mvc->db->spring ioc->log->代码 1.先了解项目数据库的表结构 ...

  2. 143. Reorder List(List)

    Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do th ...

  3. c# ftp 上传文件 与 下载文件

    接着上一篇说. 上一篇说了根据配置文件获取路径,并判断路径在服务器中是否存在.如果不存在则在服务器中建立一个. 然后就是往路径下面传输文件了.. 代码: //连接ftp private void Co ...

  4. java 线程的几个注解

    Java并发编程中,用到了一些专门为并发编程准备的 Annotation. 主要包括三类: 类 Annotation(注解) 就像名字一样,这些注解是针对类的.主有要以下三个: @ThreadSafe ...

  5. java技术文章集

    RunOOB Java 教程 深入理解Java 8 Lambda spring MVC配置详解 各种参数传递示例代码 关于spring配置文件中ref属性的设定 Spring注解Annotation的 ...

  6. excel判断新增使用字典作为页面级数据库,减少io

    前提:该机构录入的都是和该机构有关的数据,机构下的funmental(idcard唯一)和creditinfo(funmentalid唯一)不能重复所以推出以下结论:1.根据userid(机构)=&g ...

  7. Spring Boot Reference Guide

    Spring Boot Reference Guide Authors Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch,  ...

  8. Go 面向对象概念

    前言: 本文是学习<<go语言程序设计>> -- 清华大学出版社(王鹏 编著) 的2014年1月第一版 做的一些笔记 , 如有侵权, 请告知笔者, 将在24小时内删除, 转载请 ...

  9. a 标签 name 属性 页面定位 (二)

    <a href="to_url#somewhere">名字</a> <a name="somewhere">名字</a ...

  10. 【小梅哥SOPC学习笔记】Altera SOPC嵌入式系统设计教程

    Altera SOPC嵌入式系统设计教程 第1章 概述 SOPC(System On Programmable Chip,可编程的片上系统)是Altera公司提出来的一种灵活.高效的SOC解决方案.它 ...