LinkedHashMap源码分析(一)





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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值