LRUMap 实现缓存以及HashMap的原理

研究了上下文缓存的实现方案,其原理类似Apache Commons Collections 项目中LRUMap,它继承于AbstractLinkedMap 抽象类,其基本思想是将最近使用的数据放置于链表的头上,进行LRUMap进行淘汰时只需要删除链表最后一个即可。

继承关系如下图:

从AbstractHashedMap看起,在此之前先学习一下hashMap的实现原理,然后分析AbstractLinkedMap和LURMap。

1、通用的HashMap的一般原理

Hashmap实际上是一个数组和链表的结合体,通过key值得到一个hashcode,作为数组的下表,能够快速定位到value。如果多个不同的key值计算出了相同的hashcode,就会有多个value定位到数组的同一个位置,这就是所谓的冲突。这种情况下,这多个value会组成链表,访问效率就会降低,所以key值计算出来的hashcode要尽量的分散,这样就会有比较高的效率,下面是一个从网上找的一个HashMap的数据结构图:

上面提到了根据key值计算hashcode,这个计算过程叫做Hash算法,一般通用的做法是key值对数组的长度取模,当然还有很多其他精妙的算法,在此不赘述……

当hashmap中的元素越来越多的时候,冲突的几率也就越来越高(因为数组的长度是固定的),所以为了提高查询的效率,就要对hashmap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,所以这是一个通用的操作,。

hashmap什么时候进行扩容呢?当hashmap中的元素个数超过数组大小*loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能。

2、AbstractHashedMap

AbstractHashedMap实现了Map接口,并自己单独实现了Hash算法,使自己成为一个HashedMap。

API介绍如下所示,我只拣几个重要属性和方法介绍一下

http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/map/AbstractHashedMap.html

2.1属性 protected  AbstractHashedMap.HashEntry[] data;

全局数组,每个数组的元素是一个带有后续指针(next)、key、hashcode、hashvalue的数据结构,可以说所有的操作都是为了维护这个数组

2.2属性 protected static int DEFAULT_CAPACITY 

默认的数组大小,可以通过构造函数指定

2.3属性 protected  float loadFactor 

扩展因子,默认为0.75,即数组填充率达到数组大小的75%的时候,会默认调整大小,重新计算元素在数组中的位置。

2.4方法 java.lang.Object get(java.lang.Object key) 

从data[]中与链表结构中取得value

2.5方法 java.lang.Object put(java.lang.Object key, java.lang.Object value) 

首先查看该value是否在data[]中,如果存在就更新一下就完事;否则就调用addMapping方法,生成一个新的HashEntry结构,加入到data[hashcode]对应位置的链表头上。

2.6方法 java.lang.Object remove(java.lang.Object key) 

从维护的data结构中删除对应的value

2.7方法 protected  void reuseEntry(AbstractHashedMap.HashEntry entry, int hashIndex, int hashCode, java.lang.Object key, java.lang.Object value) 

???

2.7其他方法,作用见名知意

protected void addEntry(AbstractHashedMap.HashEntry entry, int hashIndex)
protected void addMapping(int hashIndex, int hashCode, java.lang.Object key, java.lang.Object value)
protected void removeEntry(AbstractHashedMap.HashEntry entry, int hashIndex, AbstractHashedMap.HashEntry previous)
protected void removeMapping(AbstractHashedMap.HashEntry entry, int hashIndex, AbstractHashedMap.HashEntry previous)

3、AbstractLinkedMap

AbstractLinkedMap继承自前面的AbstractHashedMap,在AbstractHashedMap的基础上,将所有的HashEntity维护成双向的链表

API地址如下:

http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/map/LinkedMap.html

3.1属性 protected AbstractLinkedMap.LinkEntry header

LinkEntry包含了before、after两个指针,形成双向链表
3.2方法 protected void addEntry(AbstractHashedMap.HashEntry entry, int hashIndex)

重写了父类的增加节点的方法,不但维护data[],同时维护了双向链表
3.3方法 protected void removeEntry(AbstractHashedMap.HashEntry entry, int hashIndex, AbstractHashedMap.HashEntry previous)

重写了父类的删除节点的方法,不但维护了data[],同时维护了双向链表

4、LRUMap

LRUMap也是非线程安全。主要是在父类AbstractLinedMap的基础上,在更新双向链表的时候增加了moveToMRU/removeLRU操作

4.1方法 protected  void moveToMRU(AbstractLinkedMap.LinkEntry entry) 

将entry移动到双向链表的头部

4.2方法 protected boolean removeLRU(AbstractLinkedMap.LinkEntry entry)

???
4.3方法 protected void reuseMapping(AbstractLinkedMap.LinkEntry entry, int hashIndex, int hashCode, java.lang.Object key, java.lang.Object value)

???

5、扩展

在上下文实现方案中,重写了该类,采用synchronized关键字实现了线程安全。

增加了对缓存数据大小的控制,超过一定大小则将旧的数据remove掉。

参考:

http://annegu.iteye.com/blog/539465

http://www.blogjava.net/xmatthew/archive/2012/06/28/380150.html

时间: 2024-08-09 19:51:48

LRUMap 实现缓存以及HashMap的原理的相关文章

HashMap 实现原理

深入Java集合学习系列:HashMap的实现原理 参考文献 引用文献:深入Java集合学习系列:HashMap的实现原理,大部分参考这篇博客,只对其中进行稍微修改 自己曾经写过的:Hashmap实现原理 1. HashMap概述: HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的).此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序

1.Java集合-HashMap实现原理及源码分析

哈希表(Hash  Table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出现在各类的面试题中,这里对java集合框架中的对应实现HashMap的实现原理进行讲解,然后对JDK7的HashMap的源码进行分析 哈希算法,是一类算法: 哈希表(Hash  Table)是一种数据结构: 哈希函数:是支撑哈希表的一类函数: HashMap 是 Java中用哈希数据结构实现的Ma

HashMap实现原理和源码分析

作者: dreamcatcher-cx 出处: <http://www.cnblogs.com/chengxiao/>原文:https://www.cnblogs.com/chengxiao/p/6059914.html#undefined本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在页面明显位置给出原文链接. 哈希表 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维

【转】HashMap实现原理及源码分析

哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景极其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出现在各类的面试题中,重要性可见一斑.本文会对java集合框架中的对应实现HashMap的实现原理进行讲解,然后会对JDK7中的HashMap源码进行分析. 一.什么是哈希表 在讨论哈希表之前,我们先大概了解下其它数据结构在新增.查找等基础操作上的执行性能. 数组:采用一段连续的存储单元来存储数据.对

每天学会一点点(HashMap实现原理及源码分析)

哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出现在各类的面试题中,重要性可见一斑.本文会对java集合框架中的对应实现HashMap的实现原理进行讲解,然后会对JDK7的HashMap源码进行分析. 目录 一.什么是哈希表 二.HashMap实现原理 三.为何HashMap的数组长度一定是2的次幂? 四.重写equals方法需同时重写hashC

HashMap工作原理、深入理解JVM、正则

HashMap工作原理: http://www.importnew.com/7099.html: http://blog.csdn.net/ghsau/article/details/16843543: http://blog.csdn.net/ghsau/article/details/16890151. 深入理解JVM: http://www.importnew.com/17770.html: http://www.cnblogs.com/dingyingsi/p/3760447.html.

JVM里面hashtable和hashmap实现原理

JVM里面hashtable和hashmap实现原理 文章分类:Java编程 转载 在hashtable和hashmap是java里面常见的容器类, 是Java.uitl包下面的类, 那么Hashtable和Hashmap是怎么实现hash键值对配对的呢,我们看看jdk里面的源码,分析下Hashtable的构造方法,put(K, V)加入方法和get(Object)方法就大概明白了. 一.Hashtable的构造方法:Hashtable(int initialCapacity, float lo

网络内容缓存CDN的工作原理

网络内容缓存CDN的工作原理 CDN的全称是Content Delivery Network,即内容分发网络 CDN的目的就是提高用户访问网站的响应速度 提速的基本思路 例如你的网站服务器是在北京,这时有一个广州的用户来访问你的网站 当你的网站没有使用CDN时,用户是直接通过网络读取你的服务器,这个过程就涉及到了一些网络问题,例如南北网络互相访问慢的问题,或者涉及到不同网络运营商的网络沟通问题,这些问题很可能对用户体验产生不好影响 当你的网站使用CDN后,CDN把你的网站资源复制到了全国各地的服

HashMap实现原理、核心概念、关键问题的总结

简单罗列一下较为重要的点: 同步的问题 碰撞处理问题 rehash的过程 put和get的处理过程 HashMap基础: HashMap的理论基础:维基百科哈希表 JDK中HashMap的描述:HashMap Java中HashMap的实现原理和源码解读: 文章1:Java HashMap 核心源码解读 简要介绍了容量.装载因子.阈值的作用,结合put和get源码部分介绍了大致流程.但是没有详细说类似与碰撞和碰撞的解决办法,也没有提到关于同步的问题 文章2:HashMap实现原理分析 介绍了哈希