2017-07-13 23 views
8

LRUCache için resmi Android belgelerini kontrol ettim diyor: Bir değer her erişildiğinde, bir sıranın başına kaydırılır. Tam önbelleğe bir değer eklendiğinde, bu sıranın sonundaki değer boşalır ve çöp toplama için uygun hale gelebilir. Sanırım bu, önbellek tarafından kullanılan linkedhashmap tarafından korunan iki bağlı liste. Bu davranışı kontrol etmek için LruCache kaynak kodunu kontrol ettim ve get (K tuşu) yöntemini kontrol ettim. Ayrıca, alttaki hashmap'dan değeri alan ve recordAccess yöntemini çağıran harita alma yöntemini de çağırır. sıraylaLRUCache giriş rewdering kullanırken kullanırken

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 yöntemi accessOrder true olarak ayarlanır durumunda listenin sonuna erişilen girişi taşır başka hiçbir şey yapmaz, (benim sorun için en öyle varsayalım).

/** 
    * 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); 
     } 
    } 

eleman sıranın başına taşınır söylenir yukarıdaki açıklamaya çelişkili geliyor. Bunun yerine, listenin son elemanına taşındı (head.before kullanarak). Tabii ki, burada bir şey eksik, herhangi bir yardım? LinkedHashMap ait javadoc itibaren

+0

Hangi kaynakları kontrol ettiğiniz hakkında hiçbir fikrim yok, sadece bunu görebilirim (https://android.googlesource.com/platform/frameworks/support.git/+/795b97d901e1793dac5c3e67d43c96a758fec388/v4/java/android/support /v4/util/LruCache.java#63) – pskink

+0

Aynı kaynakları kontrol ediyorum ve gerçek yeniden sıralama, LinkedHashMap sınıfında gerçekleşiyor (çünkü burası nerede tutuluyor), böylece map.get'e girmeniz gerekiyor () yöntem. –

+1

tamam, bu yüzden "LinkedHashMap" uygulamasının ayrıntılarına değil, bazı sanal "" kuyruğa "işaret ederler (haritalama tersine çevrilir) – pskink

cevap

2

Hiçbir şey kaçırmıyorsunuz, LinkedHashMap için LruCache belgelerini okuyorsunuz. LinkedHashMap, özellikle kendi accessOrder ile ilgili kendi belgelerine sahiptir. (Java docs ile aynı).

[... zaman accessOrder = gerçek ...] yineleme sırasıdır girişleri son gelen en yakın zamanda erişilen, erişilen sıradır en-son (erişim dereceden)

LinkedHashMap Son olarak en son kullanılan girişleri sonlandırır ve belgelenmiştir.Böyle önbellek teoride çalışır, ancak LinkedHashMap ayrı geriye hareket eden yineleyicinızı eklemeden nasıl uygulanacağı konusu gösterir nasıl

Pratik LruCache anlatır: sonunda son unsurları koyarak, trimming zaten mevcut (ileri hareket eden) yineleyici kullanabilirsiniz eski öğelere etkili bir şekilde erişmek (ve kaldırmak).

Burada ve şimdi removeEldestEntry ile neyin yanlış olduğunu anlayamadım. Belki de geçmişte yoktu.

1

:

üç argüman yapıcısı kullanılırsa

ve accessOrdergerçek olarak belirtilir, yineleme girdileri erişilen edildi sırayla olacaktır. Erişim emri,, ve putAll işlemlerinden etkilenen, ancak toplama görünümlerindeki işlemlerle etkilenmeyen etkilenir.

Exactly the case , o LruCache sahiptir.

public LruCache(int maxSize) { 
    if (maxSize <= 0) { 
     throw new IllegalArgumentException("maxSize <= 0"); 
    } 
    this.maxSize = maxSize; 
    this.map = new LinkedHashMap<K, V>(0, 0.75f, true); 
} 

en recordAccess() ne görelim:
void recordAccess(HashMap<K,V> m) { 
     LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; 
     if (lm.accessOrder) { // true, because `LruCache` instantiated this 
           // map with `accessOrder = true` 
      lm.modCount++; 
      remove(); // remove this `LinkedHashMapEntry` from the map 
      addBefore(lm.header); // adds this entry before the current header of 
            // the map, thus this entry becomes the header 
     } 
    } 

Bunun yerine (head.before kullanarak) listenin son öğe taşınır.

Bildirgenizin geçerli olduğunu göremiyorum.

+0

Girdinin bir başlık olması için, lm.header addBefore yönteminde değiştirilmelidir. Lm.header alanına, başlığın değişmesine neden olan herhangi bir ödev göremiyorum. –

+0

[addBefore() uygulamasında] (https://android.googlesource.com/platform/libcore/+/0976dc2/ojluni/src/main/java/java/util/LinkedHashMap.java#356) nasıl olduğunu görebilirsiniz. referanslar değiştiriliyor: giriş girişi mevcut başlık öğesi 'önce 'öğesi olarak ekleniyor ve giriş girişi' sonra 'önceki başlık öğesine işaret ediyor. Yani, sadece referanslar atılıyor. – azizbekian

+0

, öğenin başlık olarak ekleneceğine ve işaretçinin üstbilgiye işaret ettiği noktaya karar verdi. Ancak başlığın kendisi güncellenmez. Başlıktan önce bir şey eklemenin bir yolu. Ama benim problemimin temelini oluşturan lm.header (değiştirilen yönteme) alanlarını göremiyorum. –

İlgili konular