• Java集合(13)--LinkedHashMap源码分析


    HashMap使用哈希表来存储数据,并用拉链法来处理冲突。LinkedHashMap继承自HashMap,同时自身有一个链表,使用链表存储数据,不存在冲突。

    LinkedList和LinkedHashMap一样使用一个双向循环链表,但LinkedList存储的是简单的数据,并不是“键值对”。

    LinkedList和LinkedHashMap都可以维护内容的顺序,但HashMap不维护顺序。

    public class LinkedHashMap<K,V>  
        extends HashMap<K,V>  
        implements Map<K,V>  

    HashMap的init方法没有实现,但是LinkedHaqshMap已经对其实现:

    void init() {  
    //初始化一个Entry类型的header  
            header = new Entry<K,V>(-1, null, null, null);        
    header.before = header.after = header;  
        }

    LinkedHashMap中多了一个accessOrder变量,他表示迭代时候的一个顺序,若为true,则按照读取顺序排序(读得越多在链表的越后面读得越少在链表的越前面LRU,最近最少使用),若为false则按照插入顺序排序.LinkedHaqshMap的前4个构造方法可以看出,accessOrder默认为false,故按照插入顺序进行排序。

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

    LRU算法中,最少使用的页面被先换出最近使用的很可能以后还会使用

    他判断accessOrder属性,若为true,则执行一个叫做LRU的算法,将刚访问的entry移除,然后加到header前面,这样迭代的时候会优先迭代最近频繁访问的entry(不是链表头),从而就改变了迭代的顺序。

    void addEntry(int hash, K key, V value, int bucketIndex) {
          createEntry(hash, key, value, bucketIndex);
          Entry<K,V> eldest = header.after;
          if (removeEldestEntry(eldest)) {
              removeEntryForKey(eldest.key);
          } else {
              if (size >= threshold)
                  resize(2 * table.length);
          }
     }
    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
       //始终返回的是false     
    return false; }

    启发:若希望将Map当做Cache来使用,并且限制大小,只需继承LinkedHashMap并重写removeEldestEntry(Entry<K,V> eldest)方法,像这样:

    private static final int MAX_ENTRIES = 100;
     protected boolean removeEldestEntry(Map.Entry eldest) {
          return size() > MAX_ENTRIES;
     }

    实现最近被使用(LRU)缓存:

    import java.util.LinkedHashMap;
    import java.util.Map;
     
    public LRUCache<K, V> extends LinkedHashMap<K, V> {
      private int cacheSize;
     
      public LRUCache(int cacheSize) {
        super(16, 0.75, true);//排序策略
        this.cacheSize = cacheSize;
      }
  • 相关阅读:
    测试学习使用
    Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules
    web框架之Spring-MVC环境搭建
    serialVersionUID
    在eclipse中部署发布web项目 和 更改eclipseweb项目发布的路径
    servlet HttpSession 监听器
    java web 中的转发和重定向
    Spring MVC 中的 forward 和 redirect
    各个部门英语标识
    添加滚动条,内容多时显示,内容少时隐藏
  • 原文地址:https://www.cnblogs.com/pipi-style/p/4738060.html
Copyright © 2020-2023  润新知