聊聊LinkedHashMap
LinkedHashMap简介
LinkedHashMap是一个根据某种规则有序的hashmap。根据名字,我们也可以看出这个集合是有hash散列的功能的同时也有顺序。hashmap是无法根据某种顺序来访问数据的,例如放入集合的元素先后的顺序。list都有这个功能,可以根据放入集合的先后来访问具体的数据。这里大家也肯定是有疑问的,例如都已经使用了hash了,为什么还要去保证顺序访问。这个在后面的场景中解释。
LinkedHashMap的实现
当刚遇到这个集合的时候,我也疑惑,能同时满足条件的数据结构究竟是怎么样的。如果没有思考这个问题,还请看到这里好好想想。 ---------滑稽分割-------- 答案确实是没有这样的数据结构。他是两种结构的组合。一种是我们熟悉的hashmap。另外一种就是链表。数据存入集合的时候,先根据hashmap的流程存放入数组中。然后再根据链表的原则,进行链接。 如果看源码,也会发现其实没有多少方法。基本都是继承自hashmap的。
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
我们来看看串联逻辑的几个操作
节点组成
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); } }
可以看出。相比hashmap的节点。linkedhashmap主要增加before, after。可以组成一个双向链表。
节点加入
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) { LinkedHashMap.Entry<K,V> last = tail;//获取最后一个节点 tail = p;//tail指向新加入的节点 if (last == null)//链表为空 head = p; else { p.before = last; last.after = p; } } //新建节点的时候把节点加入了双向链表 Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) { LinkedHashMap.Entry<K,V> p = new LinkedHashMap.Entry<K,V>(hash, key, value, e); linkNodeLast(p); return p; }
删除情况也是类似。
节点访问
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; }
afterNodeAccess中主要是把访问的节点从原来的位置摘除,加入到尾节点,成为链表的最后一个元素。
使用场景
顺序遍历和快速定位
LinkedHashMap适合有加入顺序和快速定位的场景。我自己开发中遇到过一个场景,就是把配置顺序读取,需要按照读取的顺序访问,而且还需要根据值key直接获取值。这个场景就需要使用LinkedHashMap。
缓存
LinkedHashMap另外一个强大的功能就是做缓存。不过我们要继承一下。去重写一个方法。
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {//默认是没有操作 return false; }
这个方法在插入之后会被调用到。
void afterNodeInsertion(boolean evict) { // possibly remove eldest LinkedHashMap.Entry<K,V> first; if (evict && (first = head) != null && removeEldestEntry(first)) {//删除第一个元素 K key = first.key; removeNode(hash(key), key, null, false, true); } }
LinkedHashMap支持两种缓存策略。FIFO和LRU。大家应该也猜到控制策略的地方就是accessOrder。默认为false。就是FIFO。设置为true时就是LRU。因为在访问的时候会调整链表结构,调用afterNodeAccess会把访问的节点放入队列最后。所以每次删除first就可以达到效果。我一般会选择继承LinkedHashMap。然后重写removeEldestEntry,例如可以元素个数达到200范围true。这里需要根据具体场景来编写。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
TarsGo支持Protocol Buffer
Tars是腾讯从2008年到今天一直在使用的后台逻辑层的统一应用框架TAF(Total Application Framework),目前支持C++,Java,PHP,Nodejs,Golang语言。该框架为用户提供了涉及到开发、运维、以及测试的一整套解决方案,帮助一个产品或者服务快速开发、部署、测试、上线。 它集可扩展协议编解码、高性能RPC通信框架、名字路由与发现、发布监控、日志统计、配置管理等于一体,通过它可以快速用微服务的方式构建自己的稳定可靠的分布式应用,并实现完整有效的服务治理。目前该框架在腾讯内部,各大核心业务都在使用,颇受欢迎,基于该框架部署运行的服务节点规模达到上万个。 Tars 于2017年4月开源,并于2018年6月加入Linux 基金会,项目地址 https://github.com/TarsCloud 。 TarsGo 是Tars 的Go语言实现版本, 于2018年9月开源, 项目地址 https://github.com/TarsCloud/TarsGo Tars协议是一种类c++标识符的语言,用于生成具体的服务接口文件,Tars文件是Tars框架中客户端和...
- 下一篇
基于Python的Selenium经验总结
大家都知道,基于Web端的测试的基础框架是需要Selenium做主要支撑的,这里边给大家介绍下Web测试核心之基于Python的Selenium 一、简单介绍 Selenium 是用于测试 Web 应用程序用户界面 (UI) 的常用框架。它是一款用于运行端到端功能测试的超强工具。您可以使用多个编程语言编写测试,并且 Selenium 能够在一个或多个浏览器中执行这些测试。 二、环境安装 1. 安装python,这个。。。忽略,建议python2.7。 2. 安装基于python的selenium依赖包,命令:pip install selenium==2.53.6,你懂的。 3. 安装浏览器驱动包,推荐使用chrome浏览器的chromedriver.exe,对应chrome版本一定要对哦,不然运行不起来的,安装在哪?想放哪放哪,不过一般是放在python的根目录下。下载地址:http://chromedriver.storage.googleapis.com/index.html 4. 安装PyCharm 2.7左右版本,这个无脑安装~然后可自定义界面UI及编码风格,这个。。。忽略 ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- MySQL8.0.19开启GTID主从同步CentOS8
- Linux系统CentOS6、CentOS7手动修改IP地址
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7,8上快速安装Gitea,搭建Git服务器