java基础提高之LinkedHashMap

        进入高产模式

。这一篇呢,我们来学一哈儿LinkedHashMap,这个LinkedHashMap。在缓存算法中有一个LRU(Least Recently Used的缩写,最近最少使用)算法,我们便可以通过这个LinkedHashMap去完成这个算法,具体实现我们会在后面贴出来。现在我们进入我们探讨的正常流程。在看这一篇之前建议先去了解 HashMap

简介

  1. Map接口的哈希表与链表实现,这个跟HashMap不一样的地方有这么一个,就是有可预测的顺序,我们会在下面说到。这个实现不同于HashMap的地方是它内部维护了一个关联所有键值对的双相链表,这个链表定义了迭代的顺序是按照插入时的顺序还是访问时的顺序。

  2. LinkedHashMap提供了一个构造函数,能使原有的Map转变为LinkedHashMap,并且这个LinkedHashMap中元素的顺序与源中元素顺序相同。

  3. LinkedHashMap提供了一个构造函数LinkedHashMap(int,float,boolean) ,我们能通过这个构造函数指定排序顺序。当为ture时,LinkedHashMap会将按照访问的顺序进行排序。

  4. removeEldestEntry这个方法便是LinkedHashMap判断是否删除元素的依据,当为true时,删除第一个元素。如果要使用一般需要重写。

  5. 这个类提供所有map的可选操作,并且允许null元素。想HashMap一样,对基本操作如add、contains、remove他提供恒定时间的性能表现。并且性能比HashMap只低一点点,因为要维护一个双向链表。对所有元素进行迭代,在LinkedHashMap中这个所需要的时间与其size成正比。但是HashMap花费更多,需要与其容量成正比的时间。

  6. 有两个参数影响其性能,initial capacity与load factor 他们的定义与在HashMap中的完全相同。

  7. 这个实现不是同步的,如果有多个线程访问,并且至少有一个线程对其进行了结构修改,必须要进行额外的操作保证其线程安全性,比如使用Map m = Collections.synchronizedMap(new LinkedHashMap(...));

  8. 这里的结构改变与其他的集合类有些不同,在这个LinkedHashMap是以访问顺序进行排序时,get也算结构改变。

  9. 这个类返回的所有迭代器Iterator都是基于快速失败机制fail-fast的。

  10. 这个类返回的分裂迭代器Spliterator是后期绑定以及快速失败的,并且被标记为ORDERED。

存储结构

LinkedHashMap继承于HashMap,所以LinkedHashMap除了双向链表外,其他的都与HashMap大同小异。在这一篇,我们将关注点放到LinkedHashMap的实际使用上,所以存储结构我们用图来解释。

展示的有些乱,但是大题存储结构画出来了,与HashMap相比其实就是多了一个双向链表。

实际应用

我们现在利用LinkedHashMap来做一个简单的LRU。

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

/**
 * @author lichaobao
 * @date 2019/5/30
 * @QQ 1527563274
 */
public class LRULinkedHashMap<K,V> extends LinkedHashMap<K,V> {
    private int capacity;
    public LRULinkedHashMap(int capacity){
        super(4,0.75f,true);
        this.capacity = capacity;
    }
    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        boolean ifRemove = size() > capacity;
        if(ifRemove){
            System.out.println("内存不够即将删除:"+eldest.getKey()+"="+eldest.getValue());
        }
        return ifRemove;
    }
    public static void main(String[] args){
        Map<Integer,String> map = new LRULinkedHashMap<Integer, String>(4);
        map.put(1,"one");
        map.put(2,"two");
        map.put(3,"three");
        map.put(4,"four");
        System.out.println("==========访问前数据顺序==============");
        map.forEach((key,value)->{
            System.out.print(key+"="+value+" ");
        });
        System.out.println("\n============现在开始get(1)=============");
        System.out.println(map.get(1));
        System.out.println("==========访问1后数据顺序==============");
        map.forEach((key,value)->{
            System.out.print(key+"="+value+" ");
        });
        System.out.println("\n==============现在开始增加第五个数据 put(5,\"five\")==========");
        map.put(5,"five");
        System.out.println("================最后map中的元素以及顺序为================");
        map.forEach((key,value)->{
            System.out.print(key+"="+value+" ");
        });
    }
}
复制代码

最后运行结果如下:

总结

  1. LinkedHashMap除了多了一个双向链表外与HashMap大致相同,比如扩容、存储机制等。
  2. 支持两种自动排序,一种是按照插入时的顺序排序,一种是按照访问时的顺序排序,可以通过构造函数LinkedHashMap(int,float,boolean) 来选择。
  3. 比较适合用来做LRU
  4. 非同步容器

转载于:https://juejin.im/post/5cf26350e51d4555fd20a2de

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值