LinkedHashMap源码分析(一)

来源:互联网 发布:淘宝装修店招全屏代码 编辑:程序博客网 时间:2024/06/10 06:40





LinkedHashMap 表示链散列映射表:继承了散列映射表HashMap,实现了Map接口。LinkedHashMap用的是访问顺序而不是插入顺序,对映射表条目进行迭代。每次调用get或put方法时,受到影响的条目都会被删除并放到链表的尾部(只有条目在链表中的位置会受影响,而散列表中的桶不会受到影响,一个条目总位于键散列码对应的桶中)。访问顺序有利于实现高速缓存的“最近最少使用”。例如,可能希望将访问频率搞得元素放在内存中,访问频率低的从数据库中读取。当表中找不到所需的元素项而表又满了,就可以将迭代器加入到表中,并将枚举的前几个元素删除。这些事近期最少使用的元素。这一过程可以自动化,只需要覆盖下面的方法:

protected boolean removeEldestEntry(Map.Entry eldest)



源码里面给了一个例子,可以缓存100个元素:

 private static final int MAX_ENTRIES = 100;               protected boolean removeEldestEntry(Map.Entry eldest) {           return size() > MAX_ENTRIES;         }
每当方法放回true时,就添加一个新的条目,从而导致删除eldest条目。


这是为什么呢?看一下addEntry()方法就明白了:

    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;        if (removeEldestEntry(eldest)) {            removeEntryForKey(eldest.key);        } else {            if (size >= threshold)                resize(2 * table.length);        }    }
if(removeEldestEntry(eldest))巧妙的调用了removeEldestEntry方法。






在看一下LinkedHashMap的内部迭代器,感觉写的很好(对我来讲源码写的都很好):

private abstract class HashIterator<E> implements Iterator<E> {        Entry<K,V> next;// next entry to return        int expectedModCount;// For fast-fail        int index;// current slot        Entry<K,V> current;// current entry        HashIterator() {            expectedModCount = modCount;            if (size > 0) { // advance to first entry                Entry[] t = table;                while (index < t.length && (next = t[index++]) == null)                    ;            }        }        public final boolean hasNext() {            return next != null;        }        final Entry<K,V> nextEntry() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            Entry<K,V> e = next;            if (e == null)                throw new NoSuchElementException();            if ((next = e.next) == null) {                Entry[] t = table;                while (index < t.length && (next = t[index++]) == null)                    ;            }    current = e;            return e;        }        public void remove() {            if (current == null)                throw new IllegalStateException();            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            Object k = current.key;            current = null;            HashMap.this.removeEntryForKey(k);            expectedModCount = modCount;        }    }

expectedModCount 是迭代器内部的修改计数器,初始化的时候等于集合的modCount,当一个集合有多个迭代器时,会出现一个问题:就是迭代器a在对集合进行修改前已经有其他迭代器对集合进行了结构化修改,所以会导致两个计数器数值不一致,此时就会抛出ConcurrentModificationException同时修改异常。


0 0