LinkedHashMap

来源:互联网 发布:mac 装了office2016卡 编辑:程序博客网 时间:2024/05/22 16:57
直接先贴代码
import java.util.ConcurrentModificationException;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.NoSuchElementException;public class LinkedHashMap<K,V>    extends HashMap<K,V>    implements Map<K,V>{    private static final long serialVersionUID = 3801124242820219131L;    // 整个对象就一个头节点,只有前和后节点的引用    private transient Entry<K,V> header;    //排序规则    // true 按访问顺序    //false 按照插入顺序    private final boolean accessOrder;    //默认都是按照插入顺序,构造函数跟HashMap相同    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;    }   //实例化头节点,前后节点都指向自己    void init() {        header = new Entry<K,V>(-1, null, null, null);        header.before = header.after = header;    }    //复写了父类的方法,改方法在父类的resize方法中调用,遍历链表,然后将数据插入到Hash槽中,省去了遍历hashMap外层数组麻烦    //本身的链表不需要改变    void transfer(HashMap.Entry[] newTable) {        int newCapacity = newTable.length;        for (Entry<K,V> e = header.after; e != header; e = e.after) {            int index = indexFor(e.hash, newCapacity);            e.next = newTable[index];            newTable[index] = e;        }    }    //根据value查询直接遍历链表,比起HashMap的方法简单些    public boolean containsValue(Object value) {        // Overridden to take advantage of faster iterator        if (value==null) {            for (Entry e = header.after; e != header; e = e.after)                if (e.value==null)                    return true;        } else {            for (Entry e = header.after; e != header; e = e.after)                if (value.equals(e.value))                    return true;        }        return false;    }   // 复写get方法,添加 e.recordAccess(this);这个操作    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;    }       public void clear() {        super.clear();        header.before = header.after = header;    }        private static class Entry<K,V> extends HashMap.Entry<K,V> {        // These fields comprise the doubly linked list used for iteration.        Entry<K,V> before, after;Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {            super(hash, key, value, next);        }        /**         * Removes this entry from the linked list.         */        private void remove() {            before.after = after;            after.before = before;        }        private void addBefore(Entry<K,V> existingEntry) {            after  = existingEntry;            before = existingEntry.before;            before.after = this;            after.before = this;        }        //排序,如果是false,插入顺序,什么都不做        //如果是true 读取顺序则将改数据移动到链表的末尾        //get和put方法都会调用,put方法在父类中调用的        void recordAccess(HashMap<K,V> m) {            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;            if (lm.accessOrder) {                lm.modCount++;                remove();                addBefore(lm.header);            }        }        void recordRemoval(HashMap<K,V> m) {            remove();        }    }    private abstract class LinkedHashIterator<T> implements Iterator<T> {Entry<K,V> nextEntry    = header.after;Entry<K,V> lastReturned = null;int expectedModCount = modCount;public boolean hasNext() {            return nextEntry != header;}public void remove() {    if (lastReturned == null)throw new IllegalStateException();    if (modCount != expectedModCount)throw new ConcurrentModificationException();            LinkedHashMap.this.remove(lastReturned.key);            lastReturned = null;            expectedModCount = modCount;}Entry<K,V> nextEntry() {    if (modCount != expectedModCount)throw new ConcurrentModificationException();            if (nextEntry == header)                throw new NoSuchElementException();            Entry<K,V> e = lastReturned = nextEntry;            nextEntry = e.after;            return e;}    }    private class KeyIterator extends LinkedHashIterator<K> {public K next() { return nextEntry().getKey(); }    }    private class ValueIterator extends LinkedHashIterator<V> {public V next() { return nextEntry().value; }    }    private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {public Map.Entry<K,V> next() { return nextEntry(); }    }    // These Overrides alter the behavior of superclass view iterator() methods    Iterator<K> newKeyIterator()   { return new KeyIterator();   }    Iterator<V> newValueIterator() { return new ValueIterator(); }    Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }    //覆写HashMap中的addEntry方法,LinkedHashmap并没有覆写HashMap中的put方法,      //而是覆写了put方法所调用的addEntry方法和recordAccess方法,      //put方法在插入的key已存在的情况下,会调用recordAccess方法,      //在插入的key不存在的情况下,要调用addEntry插入新的Entry ,     //添加新的key也需要添加到链表中    void addEntry(int hash, K key, V value, int bucketIndex) {        createEntry(hash, key, value, bucketIndex);        // Remove eldest entry if instructed, else grow capacity if appropriate        Entry<K,V> eldest = header.after;        //如果有必要,则删除掉该近期最少使用的节点,          //这要看对removeEldestEntry的覆写,由于默认为false,因此默认是不做任何处理的。          if (removeEldestEntry(eldest)) {            removeEntryForKey(eldest.key);        } else {            if (size >= threshold)                resize(2 * table.length);        }    }        void createEntry(int hash, K key, V value, int bucketIndex) {        HashMap.Entry<K,V> old = table[bucketIndex];Entry<K,V> e = new Entry<K,V>(hash, key, value, old);        table[bucketIndex] = e;        e.addBefore(header);        size++;    }    //默认返回false,不做处理,如果需要删除需要从写改方法。    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {        return false;    }}




1 非线程安全的

2 结构就是HashMap 和LInkedList组合起来,比hashmap多了一个双向链表将表元素串联起来

3 可以实现LRU算法,但是是否删除元素需要重写逻辑才行

4 accessOrder属性 默认为false 插入排序。双向链表不需要做处理,访问排序为true,每次get数据时要将数据移动到双端链表的末尾,put元素肯定是在末尾的


0 0
原创粉丝点击