Java的HashSet、HashMap集合应用及底层原理,相信大家都已经很熟悉了,这里就不再赘述了。这里主要来介绍下如何Java中的LinkedHashMap集合,同时也介绍下基于LinkedHashMap的LinkedHashSet集合、LRU算法实现

LinkedHashMap

插入顺序遍历

LinkedHashMap集合是基于HashMap实现的,所以它具有HashMap的特性。但是我们在使用HashMap遍历的过程中会存在一个显著的问题,其不是按我们的插入顺序进行遍历的,而LinkedHashMap则恰好可以解决这个问题。这里我们结合JDK中LinkedHashMap的源码进行分析。在LinkedHashMap中,其为每个条目entry添加了头指针before、尾指针after,同时在整个Map中维护了链表头head、链表尾。换句话说,LinkedHashMap不仅仅是一个HashMap,同时还在内部维护了一个双向链表以便可以按插入顺序来遍历条目entry

public 

这里以添加新条目entry为例说明LinkedHashMap是如何记录保存插入顺序的。LinkedHashMap重载了HashMap的newNode、newTreeNode方法,在每次添加一个新的条目entry时,通过linkNodeLast()方法将其添加到双向链表的尾部来记录保存插入顺序

public 

对于遍历,我们以forEach方法为例来进行说明。LinkedHashMap同样重载了HashMap的forEach方法,遍历时依据链表按照从表头到表尾的顺序进行遍历,这样即保证了我们遍历时是按照元素的插入顺序进行遍历的

public 

这里我们提供一个简单的Java Demo,来验证其遍历顺序是否和我们的插入顺序一致

public 

测试结果如下,符合我们的预期

访问顺序遍历

如果研究JDK源码会发现,在LinkedHashMap中,其不仅提供了用于创建Map的常见构造器,还提供了一个 LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 构造器,其增加了我们对accessOrder字段的控制,该字段用于控制遍历的顺序,其在其它构造器中默认为false,即是按照条目entry插入顺序进行遍历,上文的测试代码也佐证了这一点

public 

现在我们结合JDK源码,以get方法为例来说明accessOrder字段的作用,可以看到当我们通过get方法访问Map中的某个entry时,如果accessOrder为true时,会将该条目entry移动到链表的最后。与之类似地,当使用put方法对已有的entry进行修改时,同样可以也会调用afterNodeAccess方法

public 

这样当我们对其进行遍历即会发现,最近被访问过的元素反而会最后输出。当然很多人会对此感到奇怪,为什么最近使用的entry不是放到表头而是放在表尾,毕竟曾经被访问过的条目entry应该优先被遍历啊。其实是因为Map中添加新元素是添加到链表的表尾。那么对于这个链表而言,表头的元素就是存在其中时间最久的。如果这是一个容量有限的Map时,就可以通过移除表头的条目来释放空间以添加新的条目。一般地,我们认为对于曾经被访问过的条目entry,其下一次依然被访问的概率会较大,故将其移动到表尾将存在时间置零。当然JDK中认为Map的容量是无限的,所以其虽然提供了一个removeEldestEntry方法来判定是否需要移除存在时间最久的条目,但是该方法结果恒为false,即不移除。下文我们会利用这一特性来实现一个基于LinkedHashMap的LRU算法

public 

这里我们提供一个简单的Java Demo,来验证曾经被访问的元素是否会被移动到链表的最后

public 

测试结果如下,符合我们的预期

LinkedHashSet

LinkedHashSet与LinkedHashMap的关系就如同HashSet与HashMap一样。LinkedHashSet内部依然是利用LinkHashMap来实现的,通过key来存储元素,而value则是无效的。值得一提的是,LinkedHashSet只支持按插入顺序进行遍历,即accessOrder字段恒为false,不可修改

LRU算法

一般情况下,内存空间是有限的昂贵的,我们不可能将所有数据全部装进内存中,当内存需要添加新数据而空间已满的情况下,我们就需要通过合适的内存管理算法策略来淘汰一些数据释放以内存空间。这里我们介绍一种常见的内存管理策略——LRU(Least Recently Used,最近最少使用)算法,其依据就是较长时间未被使用的数据其下一次被访问到的概率较低,故我们可以优先淘汰此部分的数据来释放内存

上文我们介绍了LinkedHashMap的accessOrder字段,其为true可以将被访问的数据移动到链表的表尾。这里我们就可以基于此特性来实现一个应用LRU策略的缓存。我们重载removeEldestEntry方法,当发现缓存空间已满时,即删除表头数据来释放空间

/**

现在我们编写一个测试用例,来验证其工作状态是否符合我们的预期

public 

测试结果如下

linkedhashmap遍历_Java集合:浅谈LinkedHashMap、LinkedHashSet源码及LRU算法实现相关推荐

  1. c++ list遍历_List集合就这么简单「源码剖析」

    前言 声明,本文用得是jdk1.8 前一篇已经讲了Collection的总览:Collection总览,介绍了一些基础知识. 现在这篇主要讲List集合的三个子类: ArrayList 底层数据结构是 ...

  2. HashSet及LinkedHashSet源码分析(基于JDK1.6)

    Java容器类的用途是"保存对象",分为两类:Map--存储"键值对"组成的对象:Collection--存储独立元素.Collection又可以分为List和 ...

  3. 【集合框架】JDK1.8源码分析之HashMap(一)

    转载自  [集合框架]JDK1.8源码分析之HashMap(一) 一.前言 在分析jdk1.8后的HashMap源码时,发现网上好多分析都是基于之前的jdk,而Java8的HashMap对之前做了较大 ...

  4. Java集合框架之三:HashMap源码解析

    Java集合框架之三:HashMap源码解析 版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! HashMap在我们的工作中应用的非常广泛,在工作面试中也经常会被问到,对于这样一个重要的集 ...

  5. java 集合反射_关于granite源码包CollectionUtil集合工具类获取集合反射类型、实例化各种集合类型HashSet/ArrayList等...

    一.前言 基于granite源码包org.granite.util.CollectionUtil集合工具类,分别获取集合反射类型java.lang.reflect.Type.实例化newCollect ...

  6. 详解5种红黑树的场景,从Linux内核谈到Nginx源码,听完醍醐灌顶丨Linux服务器开发丨Linux后端开发

    5种红黑树的场景,从Linux内核谈到Nginx源码,听完醍醐灌顶 1. 进程调度CFS的红黑树场景 2. 虚拟内存管理的红黑树场景 3. 共享内存slab的红黑树场景 视频讲解如下,点击观看: [干 ...

  7. java集合的遍历_java集合遍历方法总结

    java集合遍历方法总结 一.for循环遍历集合 使用条件: ①能否确定集合中的元素个数 ②集合是否可以通过整数索引值来精确位置 public static void forTraversal(){ ...

  8. Java Review - LinkedHashMap LinkedHashSet 源码解读

    文章目录 Pre 概述 数据结构 类继承关系 构造函数 方法 get() put() remove() LinkedHashSet 使用案例 - FIFO策略缓存 Pre Java Review - ...

  9. arraylist 后往前遍历_Java集合框架之ArrayList

    ArrayList介绍 ArrayList是一个数组列表.与Java数组相比,ArrayList相当于一个动态数组.它继承于AbstractList,实现了List, RandomAccess, Cl ...

最新文章

  1. vim 双剑合璧,天下无敌(笔记)
  2. CDH4.0安装及配置(二)配置网易yum源
  3. zookeeper是如何实现数据一致性的?
  4. 【矩阵乘法】Matrix Power Series(poj 3233)
  5. 如果再这么玩下去,中国的科研就没戏了
  6. windows下命令
  7. 「Linux」Linux下根据CET听力文件关键字和lcr时间对mp3进行剪辑分割
  8. java有哪些字体_java字体有哪些
  9. MATLAB求导相关知识,matlab如何求导相关阅读-matlab如何求导文章阅读-123文学网
  10. 网站整站下载工具推荐【Z】
  11. Python爬虫-模拟登入-selenium模块
  12. 多旋翼飞行器设计与控制·基本组成(笔记002)
  13. matlab中opc没有注册类,电脑中出现没有注册类别的错误提示的多种解决方法
  14. 使用videojs播放m3u8视频
  15. 社会保障psam卡 是什么_社会卡即服务
  16. OMAP3530资料
  17. [C语言]实现字符串从头尾分别输出字符的动画效果
  18. Google Scholar引用没有GB/T
  19. uni-app微信小程序+Java实现百度语音识别
  20. 湿度传感器 DHT11

热门文章

  1. MacOS Docker版本FastDFS安装指南
  2. PowerDesigner(六)-物理数据模型(PDM逆向工程)
  3. 计算机组成 交换的目的,计算机组成原理试卷.docx
  4. 报警服务器物理内存,从内存告警谈ESXi主机内存管理——内存构成
  5. 分析大数据对思维方式有何影响?了解大数据的特点、来源与数据呈现方式
  6. js正则标志/g,/i,/m说明
  7. Struts1——离BeanUtils看struts其原理1
  8. /etc/securetty文件
  9. 前端开发中的性能那点事(三)php的opcode缓存
  10. 通过实例讲解java接口和抽象类的特殊实现方法