标签:
1、开始 public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> 继承了类HashMap,实现了Map接口 2、属性 //双向链表,用于记录所有的元素 private transient Entry<K,V> header; //遍历顺序【访问顺序或插入顺序】,默认插入顺序 private final boolean accessOrder; 3、双向链表 private static class Entry<K,V> extends HashMap.Entry<K,V> { //双向链表中的上一个节点before和下一个节点after Entry<K,V> before, after; Entry(int hash, K key, V value, HashMap.Entry<K,V> next) { super(hash, key, value, next); } //从双向链表中删除元素 private void remove() { //改变当前节点的前后两个节点的引用关系,若当前节点没有被引用,则才可以被GC回收 //将前一个节点的after指向后一个节点 before.after = after; //将后一个节点的before指向前一个节点 after.before = before; } //将当前节点插入到指定节点的链表中,即指定节点的前面 private void addBefore(Entry<K,V> existingEntry) { //指定当前节点与前后节点的引用关系 //将当前节点的后一个节点指向指定节点 after = existingEntry; //将当前节点的前一个节点指向指定节点的前一个节点 before = existingEntry.before; //指定前后节点与当前节点的引用关系 //当前节点的前一个节点的后一个节点就是当前节点 before.after = this; //当前节点的后一个节点的前一个节点就是当前节点 after.before = this; } //查询或修改元素时调用 void recordAccess(HashMap<K,V> m) { LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; if (lm.accessOrder) { //当时按访问顺序时,即最近较少使用顺序LRU lm.modCount++; //删除当前节点 remove(); //当当前节点添加到链表尾部 addBefore(lm.header); } } //删除元素时调用 void recordRemoval(HashMap<K,V> m) { remove(); } } 4、构造器 //指定容量和加载因子,遍历顺序为插入顺序 public LinkedHashMap(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); accessOrder = false; } //默认加载因子,遍历顺序为插入顺序 public LinkedHashMap(int initialCapacity) { super(initialCapacity); accessOrder = false; } //默认初始化容量和加载因子,遍历顺序为插入顺序 public LinkedHashMap() { super(); accessOrder = false; } //添加元素用于初始化,遍历顺序为插入顺序 public LinkedHashMap(Map<? extends K, ? extends V> m) { super(m); accessOrder = false; } //指定容量和加载因子,以及遍历顺序 public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; } //构造对象时,初始化双向链表 @Override void init() { //初始化头节点 header = new Entry<>(-1, null, null, null); //头结点即是其自身的前一个也是后一个 header.before = header.after = header; } 5、添加 //添加时,重写了HashMap的此方法 void addEntry(int hash, K key, V value, int bucketIndex) { super.addEntry(hash, key, value, bucketIndex); //头结点的第一个节点 Entry<K,V> eldest = header.after; if (removeEldestEntry(eldest)) { //删除第一个节点 removeEntryForKey(eldest.key); } } //新增节点 void createEntry(int hash, K key, V value, int bucketIndex) { //获取老链表 HashMap.Entry<K,V> old = table[bucketIndex]; //新增节点 Entry<K,V> e = new Entry<>(hash, key, value, old); //添加到数组中 table[bucketIndex] = e; //当前节点添加到头结点尾部,添加使用前插法 e.addBefore(header); //计数 size++; } //是否删除第一个节点,即老的节点 protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return false; } 6、查找 public V get(Object key) { Entry<K,V> e = (Entry<K,V>)getEntry(key); if (e == null) return null; //记录查找的元素,用于根据访问的顺序时,维护双向链表 e.recordAccess(this); return e.value; } 参考资料: http://www.cnblogs.com/tstd/p/5059589.html
标签:
原文地址:http://www.cnblogs.com/xiaoxian1369/p/5634050.html