LinkedHashMap
是HashMap
的子类,但内部还有一个双向链表
维护键值对的顺序,每个键值对既位于哈希表
中,也位于这个双向链表
中。LinkedHashMap
支持两种顺序:一种是插入顺序
;另外一种是访问顺序
。
插入顺序
插入顺序容易理解,先添加的在前面,后添加的在后面,修改操作不影响顺序。
举个例子
LinkedHashMap<String, Integer> seqMap = new LinkedHashMap<>();
seqMap.put("c",100);
seqMap.put("d",200);
seqMap.put("a",500);
seqMap.put("d",300);
for(Map.Entry<String,Integer> entry :seqMap.entrySet()){
System.out.println(entry.getKey()+' '+entry.getValue());
}
键是按照"c"、“d”、"a"的顺序插入的,修改"d"的值不会修改顺序,所以输出为
c 100
d 300
a 500
什么时候希望保持插入顺序呢?
Map经常用来处理一些数据,其处理模式是:接收一些键值对作为输入,处理,然后输出,输出时希望保持原来的顺序。比如一个配置文件,其中有一些键值对形式的配置项,但其中有一些键是重复的,希望保留最后一个值,但还是按原来的键顺序输出, LinkedHashMap
就是一个合适的数据结构。
访问顺序
访问顺序
是什么意思呢?所谓访问是指get/pu
t操作,对一个键执行get/put操作后,其对应的键值对会移到链表末尾,所以,最末尾的是最近访问的,最开始的最久没被访问的,这种顺序就是访问顺序。
LinkedHashMap<String, Integer> seqMap = new LinkedHashMap<>(16,0.75f,true);
seqMap.put("c",100);
seqMap.put("d",200);
seqMap.put("a",500);
seqMap.get("c");
seqMap.put("d",300);
for(Map.Entry<String,Integer> entry :seqMap.entrySet()){
System.out.println(entry.getKey()+' '+entry.getValue());
}
a 500
c 100
d 300
什么时候希望按访问有序呢?
一种典型的应用是LRU缓存
,它是什么呢?缓存是计算机技术中一种非常有用的技术,是一个通用的提升数据访问性能的思路,一般用来保存常用的数据,容量较小,但访问更快。
缓存
是相对主存而言的,主存的容量更大,但访问更慢。缓存的基本假设是:数据会被多次访问,一般访问数据时都先从缓存中找,缓存中没有再从主存中找,找到后再放入缓存,这样下次如果再找相同数据访问就快了。
缓存
用于计算机技术的各个领域,比如CPU里有缓存,有一级缓存、二级缓存、三级缓存等,一级缓存非常小、非常贵、也非常快,三级缓存则大一些、便宜一些、也慢一些,
CPU缓存是相对于内存而言的,它们都比内存快。内存里也有缓存,内存的缓存一般是相对于硬盘数据而言的。硬盘也可能是缓存,缓存网络上其他机器的数据,比如浏览器访问网页时,会把一些网页缓存到本地硬盘。
LinkedHashMap
可以用于缓存,比如缓存用户基本信息,键是用户Id,值是用户信息,所有用户的信息可能保存在数据库中,部分活跃用户的信息可能保存在缓存中。
一般而言,缓存容量有限,不能无限存储所有数据,如果缓存满了,当需要存储新数据时,就需要一定的策略将一些老的数据清理出去,这个策略一般称为替换算法。