`
kim_miao
  • 浏览: 190687 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

LinkedHashMap的扩展应用

    博客分类:
  • Java
阅读更多

一. 概述:
        LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。LinkedHashMap实现与HashMap的不同之处在于,LinkedHashMap维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序(insert-order)或者是访问顺序,其中默认的迭代访问顺序就是插入顺序,即可以按插入的顺序遍历元素,这点和HashMap有很大的不同。


二.LinkedHashMap的accessOrder
    1.访问顺序
        LinkedHashMap除了支持默认的插入顺序,还支持访问顺序。所谓访问顺序(access-order)是指在迭代遍历列表中的元素时最近访问的元素会排在LinkedHashMap的尾部 。从其构造函数中可以看出当accessOrder设为true时即为访问顺序。

 public LinkedHashMap(int initialCapacity,
                   float loadFactor,
                   boolean accessOrder) {
            super(initialCapacity, loadFactor);
            this.accessOrder = accessOrder;
 }

 

     2.访问顺序时程序举例

        public class LinkedHashMapTest {
       
            public static void main(String[] args) {
                Map<String, Object> map = new LinkedHashMap<String, Object>(16, 0.75F, true);
       
                for (int i = 1; i <= 5; i++) {
                    map.put(i + "", i);
                }
                Iterator<Entry<String, Object>> iterator = map.entrySet().iterator();
                while (iterator.hasNext()) {
                    System.out.println(iterator.next().getValue());
                }
       
                map.get("2");
                map.get("3");
                System.out.println("===============split line==================");
       
                Iterator<Entry<String, Object>> iterator2 = map.entrySet().iterator();
                while (iterator2.hasNext()) {
                    System.out.println(iterator2.next().getValue());
                }
            }
        }

    
    输出如下:

        1
        2
        3
        4
        5
        ===============separator bar ======================
        1
        4
        5
        2
        3

 

    通过例子可以看出,最近经常使用的元素就放在后面,最近最少使用的就排在了链表的前面。
   
三.LinkedHashMap的扩展应用
    基于LinkedHashMap的访问顺序的特点,可构造一个LRU(Least Recently Used)最近最少使用简单缓存。也有一些开源的缓存产品如ehcache的淘汰策略(LRU)就是在LinkedHashMap上扩展的。
   
    1.LruCache的简单代码

public class LruCache<K, V> extends LinkedHashMap<K, V> {
       
            private static final long serialVersionUID = -9062508768983283300L;
           
            /** 最大容量 */
            private int maxCapacity;
       
            public LruCache(int maxCapacity) {
                super(16, 0.75f, true);
                this.maxCapacity = maxCapacity;
            }
       
            public int getMaxCapacity() {
                return this.maxCapacity;
            }
       
            public void setMaxCapacity(int maxCapacity) {
                this.maxCapacity = maxCapacity;
            }
       
            /**
             * 当列表中的元素个数大于指定的最大容量时,返回true,并将最老的元素删除。
             */
            @Override
            protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
                if (super.size() > maxCapacity) {
                    return true;
                }
                return false;
            }
        }
 

    2.测试代码

public class LruCacheTest {
       
            public static void main(String[] args) {
                LruCache<String, Object> cache = new LruCache<String, Object>(10);
       
                for (int i = 1; i <= 15; i++) {
                    cache.put(i + "", i);
                }
       
                // 此时访问指定KEY的元素
                cache.get("10");
       
                Iterator<Entry<String, Object>> iterator = cache.entrySet().iterator();
                for (; iterator.hasNext();) {
                    Entry<String, Object> entry = iterator.next();
                    System.out.println("key=" + entry.getKey() + ",value=" + entry.getValue());
                }
            }
        }

 

        输出如下:

      key=7,value=7
      key=8,value=8
      key=9,value=9
      key=11,value=11
      key=12,value=12
      key=13,value=13
      key=14,value=14
      key=15,value=15
      key=10,value=10

 


四.LinkedHashMap对上述特性支持的分析
    1.添加时删除最老元素
    LinkedHashMap如何在添加元素时把最早放入的元素删除的呢,LinkedHashMap没有提供put方法,而是使用基类HashMap的put方法,看下面的HashMap的put(K key, V value)方法的源代码:

     public V put(K key, V value) {
            if (key == null)
                return putForNullKey(value);
            int hash = hash(key.hashCode());
            int i = indexFor(hash, table.length);
            for (Entry<K,V> e = table[i]; e != null; e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                    V oldValue = e.value;
                    e.value = value;
                //HashMap中这个方法没有实现。
                    e.recordAccess(this);
                    return oldValue;
                }
            }
   
            modCount++;
            addEntry(hash, key, value, i);
            return null;
        }

 

     LinkedHashMap覆盖了HashMap中的这个addEntry(hash, key, value, i)方法,在 LinkedHashMap类中,removeEldestEntry()永远返回false;
     也就是这个方法,提供了子类更强大功能扩展的机会。

	    void addEntry(int hash, K key, V value, int bucketIndex) {
			createEntry(hash, key, value, bucketIndex);

			// Remove eldest entry if instructed, else grow capacity if appropriate
			Entry<K,V> eldest = header.after;
			//该方法返回false.
			if (removeEldestEntry(eldest)) {
			    removeEntryForKey(eldest.key);
			} else {
			    if (size >= threshold)
				resize(2 * table.length);
			}
	    }

 

   
    2.访问时重组列表

          在获取元素时,LinkedHashMap提供了get()方法,其代码如下:

      public V get(Object key) {
            Entry<K,V> e = (Entry<K,V>)getEntry(key);
            if (e == null)
                return null;
                 //最近访问的元素重新插入到最后面。
            e.recordAccess(this);
            return e.value;
      }
 

    HashMap中这个recordAccess()方法没有实现,只有空的方法体,在LinkedHashMap中的实现如下 ,也就是这个方法,将最近访问的元素给予重组,达到了LRU的目的。                

   void recordAccess(HashMap<K,V> m) {
                LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
                   //accessOrder要指定为true.
                if (lm.accessOrder) {
                lm.modCount++;
                remove();
                addBefore(lm.header);
                }
        }
        
      
 

 

分享到:
评论

相关推荐

    JAVA类集应用

    - `Map`:键值对的容器,如 `HashMap`、`TreeMap`、`LinkedHashMap`。 - `SortedMap`:有序的 Map,如 `TreeMap`,键按照自然顺序或自定义比较器排序。 - `ConcurrentMap`:线程安全的 Map,如 `...

    JAVA编程模式与范例_高级应用开发

    本书“JAVA编程模式与范例_高级应用开发”旨在深入探讨Java语言中的设计模式和最佳实践,以帮助开发者构建更高效、可维护和扩展性强的软件系统。下面我们将详细解析其中可能涉及的知识点。 1. **设计模式**: - **...

    深入Java集合学习系列

    LinkedHashMap是HashMap的一个扩展,它保持了元素的插入顺序或者按照访问顺序排序。这种特性使得LinkedHashMap在需要保持元素顺序的情况下非常有用。文件"深入Java集合学习系列:LinkedHashMap的实现原理 - 莫等闲 -...

    LRU.rar_LRU_LRU java_lru.java

    6. 扩展知识: LRU有其变体,如LFU(Least Frequently Used),根据元素的使用频率而非最后一次使用时间进行淘汰。LFU在某些情况下可能比LRU更有效,但实现起来更为复杂,因为它需要跟踪每个元素的使用次数。 总之...

    IT行业技术知识图谱秘籍.docx

    它们为我们在开发过程中的复用性、可维护性和扩展性提供了指导。常见的设计模式包括创建型模式(如单例、工厂方法、抽象工厂),结构型模式(如适配器、装饰器、代理)和行为型模式(如策略、观察者、迭代器)。掌握...

    java中MAp介绍

    `SortedMap`接口是Map接口的扩展,它除了具有Map的所有功能外,还提供了一些额外的方法来操作有序的键值对。这些方法包括获取第一个键、最后一个键以及子集等。 1. **基本方法** - `Comparator comparator()`:...

    Java集合框架常见面试题夜间阅读版.pdf

    Java集合框架是Java编程语言中非常核心且重要的知识点,它广泛应用于数据的存储、处理与检索。Java集合框架主要包括Collection接口和Map接口两大体系。Collection接口下的主要类包括List、Set和Queue等,而Map接口则...

    Java中根据汉字获得拼音的方法

    该方法对于开发需要处理中文的应用系统尤其有用。接下来,我们将探讨其实现原理、代码结构以及使用方式。 ### 实现原理 要实现从汉字转换为拼音的功能,需要借助一个包含所有常用汉字及其对应拼音的数据表。在提供...

    Java设计模式.pdf

    Java设计模式是Java开发中广泛应用的设计方法和设计思路,它对于代码复用、降低系统模块间的耦合度以及提高系统的可扩展性和维护性有着非常重要的作用。而JVM(Java虚拟机)是运行Java程序的环境,JVM设计模式通常...

    kkkNO1管理系统 (3).zip

    Map的实现类有HashMap、TreeMap、LinkedHashMap等,它们各有特点,例如HashMap提供快速的访问速度,TreeMap则保持了元素的排序。 假设【gwefnkwefoiweiofeoif (2).zip】是kkkNO1管理系统的一部分,那么它可能是该...

    Java和Android的LRU缓存及实现原理

    在Java和Android开发中,通过`LinkedHashMap`可以方便地构建高效、可扩展的缓存系统,以优化性能和内存使用。无论是Android的`LRUCache`还是自定义的LRU实现,`LinkedHashMap`都是不可或缺的工具。

    java总结.pdf

    这份文档是对Java开发者在软件设计和实现过程中常用的理论和实践的总结,覆盖了软件开发中设计模式和数据结构的核心知识点,旨在帮助开发者更好地理解和应用这些高级用法。通过学习这些设计模式和数据结构,开发者...

    Java实现Map集合二级联动示例共13页.pdf.zip

    7. **模型-视图-控制器(MVC)模式**:理解并应用MVC模式,将业务逻辑(Model)、用户界面(View)和控制逻辑(Controller)分离,使得代码更易于维护和扩展。 8. **异常处理**:在处理用户输入或访问数据时,应...

    Java实用系统开发指南

    4. **集合框架**:Java集合框架包括List、Set、Queue和Map等接口,以及ArrayList、LinkedList、HashSet、TreeSet、HashMap、LinkedHashMap等实现类。它们为数据存储和操作提供了丰富的选择,是Java中处理数据的重要...

    Java集合框架常见面试题.pdf

    * 提高了代码的可维护性:Java 集合框架提供的集合类和遍历集合的方式,提高了代码的可维护性和可扩展性。 * 提高了程序的性能:Java 集合框架提供的集合类和遍历集合的方式,提高了程序的性能和响应速度。 Java ...

    Java 72 道面试题及答案.docx

    3. 可以方便地扩展或改写集合,提高代码复用性和可操作性。 4. 降低代码维护和学习新API成本。 集合类的实现: 1. Collection接口:所有集合框架的父接口。 2. Map接口:键值对集合的父接口,实现类有HashMap、...

    Java structures

    Java 结构:深入理解与应用 Java 是一种广泛使用的面向对象的编程语言,以其平台无关性、健壮性和高效性而备受青睐。在Java的世界里,“结构”通常指的是数据结构和设计模式,它们是构建复杂软件系统的基础。下面...

    Java集合面试题 52道

    使用集合框架可以带来许多好处,包括容量自增长、提供高性能的数据结构和算法、可以方便地扩展或改写集合、提高代码复用性和可操作性,以及降低代码维护和学习新 API 成本。 5. 常用的集合类 常用的集合类有 Map ...

    Java高新技术3

    Java高新技术3涵盖了许多Java开发中的高级主题和技术,这些技术对于提升软件工程的效率、...以上是Java高新技术3中的一些关键知识点,理解和掌握这些技术将使开发者能够构建更高效、更稳定、更具扩展性的Java应用程序。

    Java基础 反射篇.md

    比如,如果需要根据不同的情况选择使用不同的数据结构(如`HashMap`, `LinkedHashMap`, 或者`WeakHashMap`),则每次都需要修改代码、编译、打包再部署,这个过程不仅繁琐而且效率低下。 #### 反射的应用 为了解决...

Global site tag (gtag.js) - Google Analytics