浅谈Map
前言
Map主要有HashMap,TreeMap,LinkHashMap,weakHashMap。HashMap的分析已经在之前的文章中有说过,HashMap链接,故本文主要是对其余的Map进行叙述
LinkHashMap
数据结构
采用HashMap和双向链表,两者二合为一。实现HashMap特性是靠继承HashMap,只是细节上的实现方式不同。实现LinkList特性是在每一个HashMap节点上增加了before和after指针来维护双向链表,有head和tail来分别指向头结点和尾节点
特性
迭代顺序可以是插入顺序,也可以是访问顺序,通过其属性accessOrder来标志(值为true时,表示按照访问顺序迭代;值为false时,表示按照插入顺序迭代),可以根据访问顺序来时先一个LRU
增加节点时需要维护节点的插入顺序,故也需要插入链表尾部;如果迭代顺序是访问顺序的话,则对节点的所有操作之后也一样需要插入到链表尾部。
实现LRU
使用LinkedHashMap实现LRU的必要前提是将accessOrder标志位设为true以便开启按访问顺序排序的模式
public class LRU<K,V> extends LinkedHashMap<K, V> implements Map<K, V>{
private static final long serialVersionUID = 1L;
public LRU(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor, accessOrder);
}
/**
* 重写LinkedHashMap中的removeEldestEntry方法,当LRU中元素多余6个时,
* 删除最不经常使用的元素
*/
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
// TODO Auto-generated method stub
if(size() > 6){
return true;
}
return false;
}
public static void main(String[] args) {
LRU<Character, Integer> lru = new LRU<Character, Integer>(
16, 0.75f, true);
String s = "abcdefghijkl";
for (int i = 0; i < s.length(); i++) {
lru.put(s.charAt(i), i);
}
System.out.println("LRU中key为h的Entry的值为: " + lru.get('h'));
System.out.println("LRU的大小 :" + lru.size());
System.out.println("LRU :" + lru);
}
}
TreeMap
- 继承AbstractMap,实现NavigableMap(支持一些导航方法,搜索小范围的集合), Cloneable,Serializable接口,是非同步的Map
- 有序的key-value集合,通过红黑树实现,基于Key进行排序。
- 构造函数可传进一个实现了comparator接口的参数进去自定义排序规则,也可以不传这个参数而使用默认的排序规则
weakHashMap
和HashMap一样,WeakHashMap 也是一个散列表,它存储的内容也是键值对映射,不过WeakHashMap的键是“弱键”。在 WeakHashMap 中,当某个键不再正常使用时,会被从WeakHashMap中被自动移除,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。 接着,WeakHashMap会根据“引用队列”,来删除“WeakHashMap中已被GC回收的‘弱键’对应的键值对”。