【发布时间】:2017-07-13 07:26:50
【问题描述】:
我查看了 LRUCache 的官方 Android 文档,其中说:每次访问一个值时,它都会移动到队列的头部。当一个值被添加到一个完整的缓存中时,该队列末尾的值被逐出并可能成为垃圾回收的条件。 我想这是由缓存使用的linkedhashmap维护的双向链表。为了检查这种行为,我检查了 LruCache 的源代码,并检查了 get(K key) 方法。它进一步调用 map 的 get 方法,该方法从底层 hashmap 中获取值并调用 recordAccess 方法。
public V get(Object key) {
LinkedHashMapEntry<K,V> e = (LinkedHashMapEntry<K,V>)getEntry(key);
if (e == null)
return null;
e.recordAccess(this);
return e.value;
}
recordAccess 方法反过来将访问的条目移动到列表的末尾,以防 accessOrder 设置为 true(对于我的问题,我们假设它是),否则它什么也不做。
/**
* This method is invoked by the superclass whenever the value
* of a pre-existing entry is read by Map.get or modified by Map.set.
* If the enclosing Map is access-ordered, it moves the entry
* to the end of the list; otherwise, it does nothing.
*/
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
addBefore(lm.header);
}
}
这听起来与上面所说的元素被移动到队列头部的语句相矛盾。相反,它被移动到列表的最后一个元素(使用 head.before)。当然,我在这里遗漏了一些东西,有什么帮助吗?
【问题讨论】:
-
我不知道你在检查什么来源,我只能看到this
-
我正在检查相同的来源,并且实际的重新排序发生在 LinkedHashMap 类中(因为这是维护列表的地方),所以你需要进入 map.get() 方法。
-
好的,所以他们指的是一些虚拟的
"queue",而不是LinkedHashMap的实现细节(映射反转) -
Uhm...
add**Before**(lm.**head**er)...该元素将成为新的头部...头部是列表中的第一个...“而是移动到列表的最后一个元素(使用head.before)。”是您的错误陈述。 -
@D.Kovács 请从源代码检查实现。私有瞬态 LinkedHashMapEntry
标头;是 addBefore 方法中未修改的标头。只有 header 的 before 字段被修改为指向新的最后一个元素。新元素基本上插入在最后一个元素和标题之间,因为它是一个循环列表。请为您的陈述提供任何来源,因为我在代码中找不到相同的来源。
标签: java android linkedhashmap android-lru-cache