我们知道我们遍历HashMap的时候,并不是按照插入顺序取出的。而是按照计算的hash然后再去计算应该存放的桶的哪一个位置。即是按照桶的顺序来遍历的,如果在同一个位置,然后接着去按照链表的顺序……

如果我们希望实现按照插入顺序来遍历,怎么办呢,LinkedHashMap就派上用场了。

那么,LinkedHashMap具有哪些特性呢?

首先:可以按照元素的添加顺序进行迭代;

其次:可以根据元素的访问顺序获取值

最后:支持删除一些老的key,但是需要自己实现,它本身只是简单的返回false.

它又是如何使得我们可以按照元素添加顺序或者元素访问顺序迭代呢?

是因为它在维持一个双向链表,可以把所有添加的Entry都维护在这个双向链表中。headentry after永远指向第一个添加的entry,添加的第一个entry before指向headentry。 然后每一次新加的entry 的 after都指向head,head的before 指向 这个新加的;然后新加的entrybefore指向他之前的那一个entry,他之前的那个entry after指向新加的这个entry.

如图示:

所以一般来说插在后面的元素,按照顺序插入这个双向的循环链表,来维护一个顺序。

一 比较重要的属性

除了继承HashMap的某些属性之外,还涉及到自己的一些属性。

//这个属性很重要,它是这个双向链表的头,初始化的时候header.

before=header.after=header;都是指向自己。

privatetransient Entry<K,V>header;

//是否按照map的访问顺序动态的改变元素的双向链表中位置

privatefinal booleanaccessOrder;

二构造方法

publicLinkedHashMap(int initialCapacity) {

super(initialCapacity);

accessOrder = false;

}

publicLinkedHashMap(int initialCapacity,floatloadFactor,boolean accessOrder) {

super(initialCapacity,loadFactor);

this.accessOrder= accessOrder;

}

它的构造方法都是基于HashMap的,但是至于能不能按照访问顺序获取数据,默认是false.

三重要的方法

void addEntry(inthash, K key,V value, intbucketIndex) {

createEntry(hash,key, value,bucketIndex);

Entry<K,V> eldest = header.after;

if(removeEldestEntry(eldest)) {

removeEntryForKey(eldest.key);

} else {

if (size>= threshold)

resize(2 *table.length);

}

}

重载了父类addEntry方法,首先创建entry,如果需要删除最老的数据,就把第一个数据给删掉,因为header.after始终指向的是链表第一个数据。

void createEntry(inthash, K key,V value, intbucketIndex) {

HashMap.Entry<K,V>old = table[bucketIndex];

Entry<K,V> e =new Entry<K,V>(hash,key, value, old);

table[bucketIndex] = e;

e.addBefore(header);

size++;

}

产生新的Entry,放入桶中,如果i相同,则放入单向链表。

e.addBefore开始构建双向链表。

privatevoid addBefore(Entry<K,V>existingEntry) {

after  = existingEntry;

before = existingEntry.before;

before.after = this;

after.before = this;

}

如图示:

publicV get(Object key) {

Entry<K,V> e =(Entry<K,V>)getEntry(key);

if (e==null)

return null;

e.recordAccess(this);

return e.value;

}

//recordAccess方法就是,只要你访问了某个enrty,我就把这个entry删掉,然后放到第一个位置上,然后下次访问的时候,这个就是第一个

void recordAccess(HashMap<K,V>m){

LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;

if (lm.accessOrder){

lm.modCount++;

remove();

addBefore(lm.header);

}

}

在遍历的时候,这个类很重要:

privateabstract class LinkedHashIterator<T>implements Iterator<T> {

Entry<K, V> nextEntry = header.after;

Entry<K, V> lastReturned = null;

int expectedModCount =modCount;

//我们判断有没有遍历完的依据就是nextEntry不等于 header,只要不是header就表示还有。

public boolean hasNext() {

return nextEntry !=header;

}

public void remove() {

if (lastReturned ==null)

throw new IllegalStateException();

if (modCount!= expectedModCount)

throw new ConcurrentModificationException();

LinkedHashMap.this.remove(lastReturned.key);

lastReturned =null;

expectedModCount =modCount;

}

Entry<K, V>nextEntry() {

if (modCount!= expectedModCount)

throw new ConcurrentModificationException();

if (nextEntry ==header)

throw new NoSuchElementException();

Entry<K, V>e =lastReturned =nextEntry;

nextEntry =e.after;

return e;

}

}

JDK1.7 深入理解 LinkedHashMap相关推荐

  1. java mysql lru_Java集合详解5:深入理解LinkedHashMap和LRU缓存

    今天我们来深入探索一下LinkedHashMap的底层原理,并且使用linkedhashmap来实现LRU缓存. 摘要:HashMap和双向链表合二为一即是LinkedHashMap.所谓Linked ...

  2. Java集合详解5:深入理解LinkedHashMap和LRU缓存

    <Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...

  3. 理解LinkedHashMap

    1. LinkedHashMap概述: LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap. LinkedH ...

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

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

  5. LinkedHashMap

    LinkedHashMap 上两篇文章讲了HashMap,HashMap是一种非常常见.非常有用的集合,并且在多线程情况下使用不当会有线程安全问题. 不过HashMap有一个问题,就是迭代HashMa ...

  6. 图解集合6:LinkedHashMap

    初识LinkedHashMap 上两篇文章讲了HashMap和HashMap在多线程下引发的问题,说明了,HashMap是一种非常常见.非常有用的集合,并且在多线程情况下使用不当会有线程安全问题. 大 ...

  7. Java面试之Java基础上册(含答案)

    JAVA中的几种基本数据类型是什么,各自占用多少字节. int 32bit short 16bit long 64bit byte 8bit char 16bit float 32bit double ...

  8. java学习总结之集合框架

    前言 在JDK1.2之前,java是没有完整的集合框架的,只有一些简单的可以扩展的容器类,如Vector.Stack.Hashtable等,这些容器类它们解决了数组不能动态扩容和使用复杂的问题,到了J ...

  9. Collection集合类和Map接口各实现类详解

    Java的集合类(collection接口和Map) 一.集合概述 集合:集合是java中提供的一种容器,可以用来存储多个数据. 集合和数组既然都是容器,它们有啥区别呢? 数组的长度是固定的.集合的长 ...

最新文章

  1. vsearch2.8.1使用和命令简介——中文帮助文档(免费64位版usearch)
  2. [Bzoj1061][Noi2008]志愿者招募(费用流)
  3. opencv+dlib人脸关键点检测cpp版
  4. Linux 修改主机名 和 ip 映射关系
  5. 全国计算机等级考试题库二级C操作题100套(第71套)
  6. python语言太差_Python语言 最差实践
  7. 大数据学习入门看什么书?大数据新手怎么入门?
  8. 无线通信原理之OFDM技术
  9. 毕业设计中使用支付宝沙箱完成在线支付流程
  10. Performs recursive(递归) glob(全局) with given suffix and rootdir,使用os.walk(rootdir)和filename.endswith(s
  11. 100%概率与任意好友获取QQ幸运字符的方法
  12. 英語專家談英語學習認識方法
  13. live555 官方网站源码下载地址
  14. 彻底删除的文件怎么恢复,恢复删除文件的方法
  15. abaqus python_ABAQUS-Python 批处理
  16. SQL TIMESTAMP 时间日期比较语句
  17. 学习记录557@flowable流程回退与终止
  18. 电容笔做的比较好的品牌有哪些?好用电容笔测评
  19. oem客户工程流程图_新产品OEM开发及生产流程图
  20. 数据盘扩容(数据不丢失)

热门文章

  1. led投影仪能换大功率灯吗_LED大功率洗墙灯怎么防水
  2. Python机器学习:梯度下降法002模拟实现梯度下降法
  3. 计算机需要会那些英语翻译,计算机专业英语翻译
  4. idata界面_iData手持终端常见问题集,持续更新中...
  5. java重载能否发生多次,java - 在Java中重载和多次调度 - SO中文参考 - www.soinside.com...
  6. Java 算法 能量项链
  7. NLTK使用英文词性还原
  8. 搭建远程jupyter服务器并从本地连接,有浏览器的地方就有Python!
  9. 滨州智能dcs系统推荐_推荐一:智能变电站监控系统典型作业培训教材
  10. java 线程 wait 一定要同步_java中使用wait就得使用同步锁,而且2个线程必须都使用同步代码块,否则就会异常...