Java LinkedHashMap Example

LinkedHashMap 使用場(chǎng)景: 我們需要構(gòu)建一個(gè)空間占用敏感的資源池庐扫,并且希望可以自動(dòng)的釋放掉不常訪問(wèn)的對(duì)象饭望。

構(gòu)造函數(shù)

/**

* Constructs an empty {@code LinkedHashMap} instance with the

* specified initial capacity, load factor and ordering mode.

*

* @param  initialCapacity the initial capacity

* @param  loadFactor      the load factor

* @param  accessOrder    the ordering mode - {@code true} for

*        access-order, {@code false} for insertion-order

* @throws IllegalArgumentException if the initial capacity is negative

*        or the load factor is nonpositive

*/

public LinkedHashMap(int initialCapacity,

                    float loadFactor,

                    boolean accessOrder) {

super(initialCapacity, loadFactor);

    this.accessOrder = accessOrder;

}

initialCapacity 默認(rèn)值是16, loadFactor 默認(rèn)值是0.75f, accessOrder默認(rèn)值是false(也就是默認(rèn)的ordering mode是insertion-order)形庭,如果把a(bǔ)ccessOrder 設(shè)置為true杰妓,這時(shí)候ordering mode 就是 access-order.

那么indertion-order 和access-order 有什么不同呢?

LinkedHashMap 提供了一個(gè) removeEldestEntry 的方法:

/**
     * Returns {@code true} if this map should remove its eldest entry.
     * This method is invoked by {@code put} and {@code putAll} after
     * inserting a new entry into the map.  It provides the implementor
     * with the opportunity to remove the eldest entry each time a new one
     * is added.  This is useful if the map represents a cache: it allows
     * the map to reduce memory consumption by deleting stale entries.
     *
     * <p>Sample use: this override will allow the map to grow up to 100
     * entries and then delete the eldest entry each time a new entry is
     * added, maintaining a steady state of 100 entries.
     * <pre>
     *     private static final int MAX_ENTRIES = 100;
     *
     *     protected boolean removeEldestEntry(Map.Entry eldest) {
     *        return size() &gt; MAX_ENTRIES;
     *     }
     * </pre>
     *
     * <p>This method typically does not modify the map in any way,
     * instead allowing the map to modify itself as directed by its
     * return value.  It <i>is</i> permitted for this method to modify
     * the map directly, but if it does so, it <i>must</i> return
     * {@code false} (indicating that the map should not attempt any
     * further modification).  The effects of returning {@code true}
     * after modifying the map from within this method are unspecified.
     *
     * <p>This implementation merely returns {@code false} (so that this
     * map acts like a normal map - the eldest element is never removed).
     *
     * @param    eldest The least recently inserted entry in the map, or if
     *           this is an access-ordered map, the least recently accessed
     *           entry.  This is the entry that will be removed it this
     *           method returns {@code true}.  If the map was empty prior
     *           to the {@code put} or {@code putAll} invocation resulting
     *           in this invocation, this will be the entry that was just
     *           inserted; in other words, if the map contains a single
     *           entry, the eldest entry is also the newest.
     * @return   {@code true} if the eldest entry should be removed
     *           from the map; {@code false} if it should be retained.
     */
    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        return false;
    }

這個(gè)方法默認(rèn)返回false也就是說(shuō)LinkedHashMap在新增鍵值對(duì)時(shí)LinkedHashMap并不會(huì)刪除已有的“老的”元素碘勉,我們可以重寫(xiě)這個(gè)方法用來(lái)刪除map里面最“老”的元素巷挥。
比如,如果我們希望在增加第4個(gè)元素時(shí)希望刪掉它里面最“老”的元素验靡。
在創(chuàng)建鏈表的時(shí)候重寫(xiě)該方法倍宾, return size() >3 的意思是:當(dāng)LinkedHashMap里面的元素個(gè)數(shù)大于3時(shí),就啟動(dòng)LinkedHashMap 刪除最“老”元素的功能:

LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>(16, 0.75f, true){
            @Override
            protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
                return size() > 3;
            }
        };

我們給LinkedHashMap添加3個(gè)元素胜嗓,然后通過(guò)foreach來(lái)打印它里面的所有元素高职。

        linkedHashMap.put("project1", "1");
        linkedHashMap.put("project2", "2");
        linkedHashMap.put("project3", "3");

        linkedHashMap.forEach((k, v) -> {
            System.out.println("key: " + k + ", value: " + v);
        });

輸出結(jié)果:

key: project1, value: 1
key: project2, value: 2
key: project3, value: 3

這時(shí)候我們添加第4個(gè)元素,

        linkedHashMap.put("project1", "1");
        linkedHashMap.put("project2", "2");
        linkedHashMap.put("project3", "3");

        linkedHashMap.forEach((k, v) -> {
            System.out.println("key: " + k + ", value: " + v);
        });

        linkedHashMap.put("project4", "4");
        System.out.println("After changed;");

        linkedHashMap.forEach((k, v) ->{
            System.out.println("key: " + k + ", value: " + v);
        });

輸出結(jié)果:

key: project1, value: 1
key: project2, value: 2
key: project3, value: 3
After changed;
key: project2, value: 2
key: project3, value: 3
key: project4, value: 4

可以看到LinkedHashMap 把鍵值對(duì)("project1":"1")的元素刪除了辞州,新增了("project4":"4")的元素怔锌,元素的總數(shù)還是保持3個(gè)。
我們已經(jīng)設(shè)置了LinkedHashMap的ordering mode 為access-order, 但是我們并沒(méi)有訪問(wèn)LinkedHashMap任何其中的一個(gè)元素,所以在刪除元素時(shí)埃元,LinkHashMap刪除了第一個(gè)被添加進(jìn)去的元素涝涤。
我們?cè)囍L問(wèn)下LinkedHashMap里面的元素,看看被刪除的元素會(huì)是哪一個(gè)岛杀。

        linkedHashMap.put("project1", "1");
        linkedHashMap.put("project2", "2");
        linkedHashMap.put("project3", "3");

        linkedHashMap.forEach((k, v) -> {
            System.out.println("key: " + k + ", value: " + v);
        });

        //訪問(wèn)了第一個(gè)元素
        linkedHashMap.get("project1");

        linkedHashMap.put("project4", "4");

        System.out.println("After changed;");
        linkedHashMap.forEach((k, v) ->{
            System.out.println("key: " + k + ", value: " + v);
        });

輸出結(jié)果:

key: project1, value: 1
key: project2, value: 2
key: project3, value: 3
After changed;
key: project3, value: 3
key: project1, value: 1
key: project4, value: 4

可以看到第二個(gè)被添加進(jìn)LinkedHashMap的元素被刪除了阔拳。(第二個(gè)元素和第三個(gè)元素都沒(méi)有被訪問(wèn),但是第二個(gè)元素是先于第三個(gè)元素被添加到LinkedHashMap中的)类嗤。

我們可以得到如下結(jié)論:
如果沒(méi)有重寫(xiě)LinkedHashMap removeEldestEntry方法糊肠,那么新添加元素時(shí),它不會(huì)刪除已經(jīng)存在的元素遗锣。
如果重寫(xiě)了LinkedHashMap removeEldestEntry方法货裹,accessOrder為false,當(dāng)新添加元素時(shí)精偿,它會(huì)刪除Map里正存在的并且最早被添加進(jìn)來(lái)的元素泪酱。
如果重寫(xiě)了LinkedHashMap removeEldestEntry方法, 并且accessOrder為true,當(dāng)新添加元素時(shí)还最,(1)如果map里面有未被訪問(wèn)過(guò)的元素墓阀,它會(huì)刪除未被訪問(wèn)過(guò)的所有元素里最早被添加進(jìn)去的元素。(2)如果map里所有的元素都被訪問(wèn)過(guò)拓轻,它會(huì)刪除最早被訪問(wèn)過(guò)的元素斯撮。

注意:
當(dāng) ordering mode是 insertion-order 時(shí),更新(reinsert)一個(gè)已經(jīng)存在的鍵值并不會(huì)改變insertion order.

當(dāng)ordering mode是 access-order時(shí)扶叉,put, putIfAbsent,
get, getOrDefault, compute, computeIfAbsent,
computeIfPresent, merge 等方法都會(huì)改變 access order 的順序勿锅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市枣氧,隨后出現(xiàn)的幾起案子溢十,更是在濱河造成了極大的恐慌,老刑警劉巖达吞,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件张弛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡酪劫,警方通過(guò)查閱死者的電腦和手機(jī)吞鸭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)覆糟,“玉大人刻剥,你說(shuō)我怎么就攤上這事√沧郑” “怎么了造虏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵御吞,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我漓藕,道長(zhǎng)陶珠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任撵术,我火速辦了婚禮背率,結(jié)果婚禮上话瞧,老公的妹妹穿的比我還像新娘嫩与。我一直安慰自己,他們只是感情好交排,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著埃篓,像睡著了一般处坪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上架专,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天同窘,我揣著相機(jī)與錄音,去河邊找鬼部脚。 笑死想邦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的委刘。 我是一名探鬼主播丧没,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼锡移!你這毒婦竟也來(lái)了呕童?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤淆珊,失蹤者是張志新(化名)和其女友劉穎夺饲,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體施符,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钞支,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了操刀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烁挟。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖骨坑,靈堂內(nèi)的尸體忽然破棺而出撼嗓,到底是詐尸還是另有隱情柬采,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布且警,位于F島的核電站粉捻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏斑芜。R本人自食惡果不足惜肩刃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望杏头。 院中可真熱鬧盈包,春花似錦、人聲如沸醇王。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)寓娩。三九已至叛氨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間棘伴,已是汗流浹背寞埠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留焊夸,地道東北人仁连。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像淳地,于是被迫代替她去往敵國(guó)和親怖糊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361