Java技术之LinkedHashMap

在Android开发过程中,遇到需要处理大量图片显示问题时,需要运用缓存机制。而Java中已经为我们提供了很好的工具LinkedHashMap,为我们实现LRU算法提供了很大的便利。下面结合LinkedHashMap源码来了解其原理。

1.LinkedHashMap结构

LinkedHashMap继承了HashMap底层是通过Hash表+单向链表实现Hash算法,内部自己维护了一套元素访问顺序的列表。

LinkedHashMap与HashMap的区别是在于LinkeedHashMap每个元素插入表中时,就会并入到双向链表中。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。当访问顺序时,每次调用get或者put,受到影响的条目将从当前的位置删除,并放到链表条目的尾部,在这里只是链表中位置变化受到影响,而散列表中的桶不会受影响。

2.LinkedHashMap实现

2.1记录顺序

Linked内部含有一个private transient Entry header;来记录元素插入的顺序或者是元素被访问的顺序。

决定记录顺序的是由初始化时private final boolean accessOrder;

AccessOrder。默认为false,即插入顺序,true为访问顺序。

2.2构造函数

1   public LinkedHashMap(int initialCapacity,
2                          float loadFactor,
3                          boolean accessOrder) {
4         super(initialCapacity, loadFactor);
5         this.accessOrder = accessOrder;
6     }

initialCapacity是初始化表的大小,loadFactor是装载因子,默认0.75,accessOrder是指定记录的顺序,访问顺序还是插入顺序。后面的true表明LinkedHashMap按照访问的次序来排序。按照访问的次序来排序的含义:当调用LinkedHashMap的get(key)或者put(key, value)时,碰巧key在map中被包含,那么LinkedHashMap会将key对象的entry放在线性结构的最后。按照插入顺序来排序的含义:调用get(key), 或者put(key, value)并不会对线性结构产生任何的影响。

2.3获取记录

1     public V get(Object key) {
2         Entry<K,V> e = (Entry<K,V>)getEntry(key);
3         if (e == null)
4             return null;
5         e.recordAccess(this);
6         return e.value;
7     }

如果key存在,执行recordAccess(this);

1   void recordAccess(HashMap<K,V> m) {
2             LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
3             if (lm.accessOrder) {
4                 lm.modCount++;
5                 remove();
6                 addBefore(lm.header);
7             }
8         }

recordAccess方法会accessOrder为true会先调用remove清除当前首尾元素的指向关系,之后调用addBefore方法,将当前元素加入header之前。

 1   /**
 2          * Removes this entry from the linked list.
 3          */
 4         private void remove() {
 5             before.after = after;
 6             after.before = before;
 7         }
 8
 9         /**
10          * Inserts this entry before the specified existing entry in the list.
11          */
12         private void addBefore(Entry<K,V> existingEntry) {
13             after  = existingEntry;
14             before = existingEntry.before;
15             before.after = this;
16             after.before = this;
17         }

2.4获取数据

LinkedHashMap put方法时继承HashMap的put方法,但是需要重写其中的方法

 1     public V put(K key, V value) {
 2         if (key == null)
 3             return putForNullKey(value);
 4         int hash = hash(key.hashCode());
 5         int i = indexFor(hash, table.length);
 6         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
 7             Object k;
 8             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
 9                 V oldValue = e.value;
10                 e.value = value;
11                 e.recordAccess(this);
12                 return oldValue;
13             }
14         }
15
16         modCount++;
17         addEntry(hash, key, value, i);
18         return null;
19     }

2.5删除最久未被访问数据

1  protected boolean removeEldestEntry(Map.Entry eldest) {
2         return false;
3     }

LinkedHashMap中一个方法,当调用put(key, value)的时候,HashMap判断是否要自动增加map的size的作法是判断是否超过threshold, LinkedHashMap则进行了扩展,如果removeEldestEntry方法return false;(默认的实现),那么LinkedHashMap跟HashMap处理扩容的方式一致;如果removeEldestEntry返回 true,那么LinkedHashMap会自动删掉最不常用的那个entry(也就是header线性表最前面的那个)。这一特点可以很好实现缓存机制。

3.缓存机制简单实现

 1 import java.util.Iterator;
 2 import java.util.LinkedHashMap;
 3
 4 public class LRULinkedHashMap<K,V> extends LinkedHashMap<K, V>{
 5
 6     private static final int INIT_CAPACITY=10;
 7     private static final int MAX_SIZE=6;
 8     private static final float LOAD_FACTOR=0.75f;
 9
10     public LRULinkedHashMap() {
11         super(INIT_CAPACITY, LOAD_FACTOR, true);
12     }
13
14     @Override
15     protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
16         return size()>MAX_SIZE;
17     }
18
19     public static void main(String[] args) {
20
21         LRULinkedHashMap<String, String> lruLinkedHashMap=new LRULinkedHashMap<String,String>();
22         lruLinkedHashMap.put("1", "A");
23         lruLinkedHashMap.put("2", "B");
24         lruLinkedHashMap.put("3", "C");
25         lruLinkedHashMap.put("4", "D");
26         lruLinkedHashMap.put("5", "E");
27         lruLinkedHashMap.put("6", "F");
28         lruLinkedHashMap.put("7", "G");
29         lruLinkedHashMap.put("8", "H");
30         lruLinkedHashMap.put("9", "I");
31         lruLinkedHashMap.put("10", "J");
32         lruLinkedHashMap.put("11", "K");
33         Iterator<String> iterator=lruLinkedHashMap.keySet().iterator();
34         while(iterator.hasNext()){
35             System.out.print(iterator.next()+"  ");
36         }
37     }
38
39 }

结果显示:

6  7  8  9  10  11

Java技术之LinkedHashMap

时间: 2024-07-31 13:48:21

Java技术之LinkedHashMap的相关文章

Java技术的特点

Java技术是一套完整的IT行业解决方案,其中包含了很多技术.最初是从解决家电设备联网通讯的方案发展起来的,其特点适用于Internet,于是在Internet广泛应用的环境下,迅速发展成为一种计算机语言.一个平台.一个网络计算的架构. 从整体上划分,Java技术可分成Java编程语言和Java平台.Java编程语言是一种高级编程语言,Java平台是指程序运行的硬件或软件环境. Java编程语言的特征: 1.简单易用 2.面向对象 3.跨平台,可移植 4.多线程 5.健壮性 6.安全性 7.动态

【JAVA】基于MVC架构Java技术荟萃案例演练

基于JAVA-MVC技术的顾客管理项目案例总结 作者 白宁超 2016年6月9日22:47:08 阅读前瞻:本文源于对javaweb相关技术和资料汇总,涉及大量javaweb基础技术诸如:Servlet运行原理.Get/Post请求的区别.jsp的基本原理和运行框架.jsp的9大隐含对象的使用.MVC开发模式的使用.构建封装自己dao代码库.以及基于MVC的增删改查操作等:小结最后还有面向接口编程的多数据源配置与存储,以及工厂模式的使用.除此之外,后续文章会对cookie.session.Jav

JAVA技术专题综述之线程篇(1)

本文详细介绍JAVA技术专题综述之线程篇 编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield(),join() 还有一个重要的关键字:synchronized 本文将对以上内容进行讲解. 一:run()和start() 示例1: public cla ThreadTest extends Thread{public void run(){for(int i=0;i<10;i++){Syste

java技术栈:一、java编程语言概述

Java是一种编程语言,起源于20世纪90年代初Sun公司的一个叫Green的项目,该项目主要目的是是开发嵌入家用电器的分布式软件系统,从而使电器更加智能化.因为项目小组成员皆为C++的高手(那个年代正式C++流行的年代),于是采用C++进行系统开发,但在开发过程中发现C++语言本身的特性所导致的问题无法有效的解决,比如:过于复杂.安全性差等.于是项目小组只好另辟蹊径,在"简单的.可靠的.紧凑的并易于移植的"的框架内开发了一个小型的计算机语言,用于编写消费者的电子产品中的程序,当时这款

Java技术综述

自己打算好好学习下Java,所以想先明晰Java开发中到底有哪些技术,以便以后学习的过程中,可以循序渐进,随着学习的深入,本文将不断更新. Java基础教程将Java的入门基础知识贯穿在一个实例中,逐步深入,可以帮助你快速进入Java编程的世界.万事开头难,逐步跟着这个教程走一遍,对Java应该就会有一种入门的感觉了.然后再去学习更高级的主题,或者更深入地学习其中的某些知识点. 首先学习Java的一些基础知识,包括: Java开发环境安装与配置 Eclipse的安装与使用 面向对象基础 基本数据

第01章 Java 技术概览

/**@前言: Java是Sun公司推出的程序设计语言,拥有面向对象.跨平台.分布式.高性能.可移植等优点和特性,是目前应用最广的编程语言之一.Java语言实现面向对象思想的三大特性:继承.多态.封装.Java语言可以制作网站后台.大型网络游戏.多媒体开发,而且还能够操作各种操作系统(linux.Android等) @第一章 Java 技术概览 Java由两部分组成:Java API + Java VM -- Java编程接口 + Java虚拟机.Java特性:跨平台.面向对象.分布式.多线程.

(转)如何学习Java技术?谈Java学习之路

51CTO编者注:这篇文章已经是有数年“网龄”的老文,不过在今天看来仍然经典.如何学习Java?本篇文章可以说也是面对编程初学者的一篇指导文章,其中对于如何学习Java的步骤的介绍,很多也适用于开发领域其他技能的学习. [在原先<学好Java之我见>的基础上重新整理而成] Java - 近10年来计算机软件发展过程中的传奇,其在众多开发者心中的地位就如“屠龙刀”.“倚天剑”. Java是个平台,我只想说说我对学好Java的一点看法,希望对初学者有所帮助. 1. 思考一下 学习Java之前,先别

《深入理解Java虚拟机》第一部分(Java技术体系,Java虚拟机,Java技术趋势)

第一部分 走进Java 1.Java技术体系 Sun官方定义的Java技术体系包括一下几个组成部分: Java程序设语言 各种硬件平台上的Java虚拟机 Class文件格式 Java API类库 第三方Java类库 JDK是用于支持Java程序开发的最小环境,Java程序设计语言.Java虚拟机.JavaAPI类库统称为JDKJRE是支持Java程序运行的标准环境,JavaAPI类库中的JavaSEAPI子集和Java虚拟机统称为JRE 按照Java技术关注的重点业务领域来分,Java技术体系可

Java技术之垃圾收集

Java中垃圾收集Garbage Collection GC提供了内存管理机制,使得应用程序不需要关注内存时如何释放,内存用完之后,垃圾收集会进行收集,这样就减轻了因人为管理内存而造成的内存错误. 1.常见的垃圾收集策略 所谓的垃圾收集算法都面临一个问题,那就是找出应用程序不可到达的内存块,然后将其释放.这里不可到达主要指应用程序中没有内存块的引用了,而可到达主要指这个对象被跟引用或者被另一个可到达的对象引用.常见的策略有引用计数,跟踪收集器. Java技术之垃圾收集,布布扣,bubuko.co