Java學習之LinkedHashMap學習總結

總李寫程式碼發表於2016-07-31

前言:

     在學習LRU演算法的時候,看到LruCache原始碼實現是基於LinkedHashMap,今天學習一下LinkedHashMap的好處以及如何實現lru快取機制的。

需求背景:

     LRU這個演算法就是把最近一次使用時間離現在時間最遠的資料刪除掉,而實現LruCache將會頻繁的執行插入、刪除等操作,我們就會想到使用LinkedList,但是我們又要基於Key-Value來儲存資料,這個時候我們就會想起HashMap,但是HashMap不能像linkedList那樣保留資料的插入順序,如果要使用HashMap的話可以使用它的一個子類LinkedHashMap。

LinkedHashMap介紹:

     LinkedHashMap是Map介面雜湊表和連結列表實現,具有可預知的迭代順序。此實現提供所有可選的對映操作,並允許使用null值和null鍵。此類不保證對映的順序,特別是它不保證該順序恆久不變, LinkedHashMap實現與HashMap的不同之處在於,後者維護著一個執行於所有條目的雙重連結列表。此連結列表定義了迭代順序,該迭代順序可以是插入順序或者是訪問順序。根據連結串列中元素的順序可以分為:按插入順序的連結串列,和按訪問順序(呼叫get方法)的連結串列。預設是按插入順序排序,如果指定按訪問順序排序,那麼呼叫get方法後,會將這次訪問的元素移至連結串列尾部,不斷訪問可以形成按訪問順序排序的連結串列。 可以重寫removeEldestEntry方法返回true值指定插入元素時移除最老的元素。更多關於LinkedHashMap的知識介紹請檢視這篇部落格,部落格地址:http://www.cnblogs.com/children/archive/2012/10/02/2710624.html

LinkedHashMap使用:

因為我們這裡為了實現LRU演算法,排序方式 設定為true 訪問順序排序

        int initialCapacity = 10;//初始化容量
        float loadFactor = 0.75f;//載入因子,一般是 0.75f
        boolean accessOrder = true;//排序方式 false 基於插入順序  true  基於訪問順序
        Map<String, Integer> map = new LinkedHashMap<>(initialCapacity, loadFactor, accessOrder);

具體看下效果:

   for (int i = 0; i < 10; i++) {
            map.put(String.valueOf(i), i);
        }
        //訪問前順序
        for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, Integer> next = it.next();
            Log.e(TAG, "linkedMap--before-->" + next.getKey());
        }

        //模擬訪問
        map.get("5");

        //訪問後資料
        for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, Integer> next = it.next();
            Log.e(TAG, "linkedMap--after-->" + next.getKey());
        }
    }

執行結果發現訪問過的5未知發生了變化 說明是基於訪問排序的。我們接下來再看下如何移除過期的。

       final int initialCapacity = 10;//初始化容量
        float loadFactor = 0.75f;//載入因子,一般是 0.75f
        boolean accessOrder = true;//排序方式 false 基於插入順序  true  基於訪問順序
        //Map<String, Integer> map = new LinkedHashMap<>(initialCapacity, loadFactor, accessOrder);
        Map<String, Integer> map = new LinkedHashMap(initialCapacity, loadFactor, accessOrder) {

            @Override
            protected boolean removeEldestEntry(Entry eldest) {
                return size() > initialCapacity;
            }
        };
        for (int i = 0; i < 15; i++) {
            map.put(String.valueOf(i), i);
        }
        //訪問前順序
        for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, Integer> next = it.next();
            Log.e(TAG, "linkedMap--before-->" + next.getKey());
        }

我們容量定的10個,我們插入15個 我們發現最先插入的五個不見了,說明LRU演算法起到效果了。

相關文章