昨日份笔试题(LinkedHashMap运用-LRU)

import java.util.LinkedHashMap;
import java.util.Map;

/*实现一个最近最少使用LRU(Least Recently Used)的缓存并为这个缓存增加大小限制
 *LinkedHashMap自身已经实现了顺序存储,默认情况下是按照元素的添加顺序存储
 * 也可以启用按照访问顺序存储,即最近读取的数据放在最前面,最早读取的数据放在最后面
 * 然后它还有一个判断是否删除最老数据的方法,默认是返回false,即不删除数据
 */
public class B<K,V> {
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String[] args) {
        B b = new B(3);
        b.put("one", 1);
        b.put("two", 2);
        b.put("three", 3);
        b.get("two") ;
        b.get("one");
        b.put("four", 4);
        System.out.println(b);
    }
    //设置初始容量
    private final int MAX_CACHE_SIZE;
    //设置加载因子
    private final float DEFAULT_LOAD_FACTOR = 0.75f;
    //
    LinkedHashMap<K, V> linkedHashMap;

    @SuppressWarnings({ "unchecked", "serial", "rawtypes" })
    public B(int cacheSize) {
        
        MAX_CACHE_SIZE = cacheSize;
        //根据cacheSize和加载因子计算hashmap的capactiy,+1确保当达到cacheSize上限时不会触发hashmap的扩容
        
        /*Math.ceil()返回一个大于或等于参数a的最小整数(double类型)
         *Math.floor()返回一个小于或等于参数a的最大整数
         *Math.round()返回最接近参数a的整数
         */
        int capacity = (int) Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTOR) + 1;
        
        // accessOrder = true; 基于访问排序
        linkedHashMap = new LinkedHashMap(capacity, DEFAULT_LOAD_FACTOR, true) {
            //重写在一定条件下删除最久未被使用的元素的方法
            @Override
            protected boolean removeEldestEntry(Map.Entry eldest) {
                //当当前集合容量大于最大容量时
                return size() > MAX_CACHE_SIZE;
            }
        };
    }
    public synchronized void put(K key, V value) {
        linkedHashMap.put(key, value);
    }
    public synchronized V get(K key) {
        return linkedHashMap.get(key);
    }
//    public synchronized void remove(K key) {
//        linkedHashMap.remove(key);
//    }
//    public synchronized Set<Map.Entry<K, V>> getAll() {
//        return linkedHashMap.entrySet();
//    }
//    public synchronized int size() {
//        return linkedHashMap.size();
//    }
//    public synchronized void clear() {
//        linkedHashMap.clear();
//    }
    @Override
    public String toString() {
        //利用append()方法与add()方法解决String产生无用对象的问题,但不像StringBuffer一样线程安全影响性能
        StringBuilder sb = new StringBuilder();
        //Map.Entry接口
        //entrySet是 java中 键-值 对的集合,Set里面的类型是Map.Entry,一般可以通过map.entrySet()得到
        for (Map.Entry entry : linkedHashMap.entrySet()) {
            //StringBuilder向末尾追加
            sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
        }
        //将StringBuilder型字符串输出
        return sb.toString();
    }    
}

LinkedHashMap

1.在HashMap的构造函数中,调用了init方法,而在HashMap中init方法是空实现,但LinkedHashMap重写了该方法,所以在LinkedHashMap的构造方法里,调用了自身的init方法

@Override
void init() {
    // 创建了一个hash=-1,key、value、next都为null的Entry
    header = new Entry<>(-1, null, null, null);
    // 让创建的Entry的before和after都指向自身,注意after不是之前提到的next
    // 其实就是创建了一个只有头部节点的双向链表
    header.before = header.after = header;
}

2.LinkedHashMap有自己的静态内部类Entry,它继承了HashMap.Entry

Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
    super(hash, key, value, next);
}

3.所以LinkedHashMap构造函数,主要就是调用HashMap构造函数初始化了一个Entry[] table,然后调用自身的init初始化了一个只有头结点的双向链表。

举个栗子:

开始时,HashMap中有Entry1、Entry2、Entry3,并设置LinkedHashMap为访问顺序

则更新Entry1时:

会先把Entry1从双向链表中删除,然后再把Entry1加入到双向链表的表尾,而Entry1在HashMap结构中的存储位置没有变化

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值