<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-13  評(píng)論-22  文章-0  trackbacks-0

    Java WeakHashMap 到底Weak在哪里,它真的很弱嗎?WeakHashMap 的適用場(chǎng)景是什么,使用時(shí)需要注意些什么?弱引用和強(qiáng)引用對(duì)Java GC有什么不同影響?本文將給出清晰而簡(jiǎn)潔的介紹。

    總體介紹

    在Java集合框架系列文章的最后,筆者打算介紹一個(gè)特殊的成員:WeakHashMap,從名字可以看出它是某種 Map。它的特殊之處在于 WeakHashMap 里的entry可能會(huì)被GC自動(dòng)刪除,即使程序員沒(méi)有調(diào)用remove()或者clear()方法。

    更直觀的說(shuō),當(dāng)使用 WeakHashMap 時(shí),即使沒(méi)有顯示的添加或刪除任何元素,也可能發(fā)生如下情況:

    • 調(diào)用兩次size()方法返回不同的值;
    • 兩次調(diào)用isEmpty()方法,第一次返回false,第二次返回true
    • 兩次調(diào)用containsKey()方法,第一次返回true,第二次返回false,盡管兩次使用的是同一個(gè)key
    • 兩次調(diào)用get()方法,第一次返回一個(gè)value,第二次返回null,盡管兩次使用的是同一個(gè)對(duì)象。

    遇到這么奇葩的現(xiàn)象,你是不是覺(jué)得使用者一定會(huì)瘋掉?其實(shí)不然,WeekHashMap 的這個(gè)特點(diǎn)特別適用于需要緩存的場(chǎng)景。在緩存場(chǎng)景下,由于內(nèi)存是有限的,不能緩存所有對(duì)象;對(duì)象緩存命中可以提高系統(tǒng)效率,但緩存MISS也不會(huì)造成錯(cuò)誤,因?yàn)榭梢酝ㄟ^(guò)計(jì)算重新得到。

    要明白 WeekHashMap 的工作原理,還需要引入一個(gè)概念:弱引用(WeakReference)。我們都知道Java中內(nèi)存是通過(guò)GC自動(dòng)管理的,GC會(huì)在程序運(yùn)行過(guò)程中自動(dòng)判斷哪些對(duì)象是可以被回收的,并在合適的時(shí)機(jī)進(jìn)行內(nèi)存釋放。GC判斷某個(gè)對(duì)象是否可被回收的依據(jù)是,是否有有效的引用指向該對(duì)象。如果沒(méi)有有效引用指向該對(duì)象(基本意味著不存在訪問(wèn)該對(duì)象的方式),那么該對(duì)象就是可回收的。這里的“有效引用”并不包括弱引用。也就是說(shuō),雖然弱引用可以用來(lái)訪問(wèn)對(duì)象,但進(jìn)行垃圾回收時(shí)弱引用并不會(huì)被考慮在內(nèi),僅有弱引用指向的對(duì)象仍然會(huì)被GC回收

    WeakHashMap 內(nèi)部是通過(guò)弱引用來(lái)管理entry的,弱引用的特性對(duì)應(yīng)到 WeakHashMap 上意味著什么呢?將一對(duì)key, value放入到 WeakHashMap 里并不能避免該key值被GC回收,除非在 WeakHashMap 之外還有對(duì)該key的強(qiáng)引用

    關(guān)于強(qiáng)引用,弱引用等概念以后再具體講解,這里只需要知道Java中引用也是分種類(lèi)的,并且不同種類(lèi)的引用對(duì)GC的影響不同就夠了。

    具體實(shí)現(xiàn)

    WeakHashMap的存儲(chǔ)結(jié)構(gòu)類(lèi)似于HashMap,讀者可自行參考前文,這里不再贅述。

    關(guān)于強(qiáng)弱引用的管理方式,博主將會(huì)另開(kāi)專(zhuān)題單獨(dú)講解。

    Weak HashSet?

    如果你看過(guò)前幾篇關(guān)于 MapSet 的講解,一定會(huì)問(wèn):既然有 WeekHashMap,是否有 WeekHashSet 呢?答案是沒(méi)有:( 。不過(guò)Java Collections工具類(lèi)給出了解決方案,Collections.newSetFromMap(Map<E,Boolean> map)方法可以將任何 Map包裝成一個(gè)Set。通過(guò)如下方式可以快速得到一個(gè) Weak HashSet

    // 將WeakHashMap包裝成一個(gè)Set
    Set<Object> weakHashSet = Collections.newSetFromMap(
            new WeakHashMap<Object, Boolean>());

    不出你所料,newSetFromMap()方法只是對(duì)傳入的 Map做了簡(jiǎn)單包裝:

    // Collections.newSetFromMap()用于將任何Map包裝成一個(gè)Set
    public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
        return new SetFromMap<>(map);
    }

    private static class SetFromMap<E> extends AbstractSet<E>
        implements Set<E>, Serializable
    {
        private final Map<E, Boolean> m;  // The backing map
        private transient Set<E> s;       // Its keySet
        SetFromMap(Map<E, Boolean> map) {
            if (!map.isEmpty())
                throw new IllegalArgumentException("Map is non-empty");
            m = map;
            s = map.keySet();
        }
        public void clear()               {        m.clear(); }
        public int size()                 { return m.size(); }
        public boolean isEmpty()          { return m.isEmpty(); }
        public boolean contains(Object o) { return m.containsKey(o); }
        public boolean remove(Object o)   { return m.remove(o) != null; }
        public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
        public Iterator<E> iterator()     { return s.iterator(); }
        public Object[] toArray()         { return s.toArray(); }
        public <T> T[] toArray(T[] a)     { return s.toArray(a); }
        public String toString()          { return s.toString(); }
        public int hashCode()             { return s.hashCode(); }
        public boolean equals(Object o)   { return o == this || s.equals(o); }
        public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
        public boolean removeAll(Collection<?> c)   {return s.removeAll(c);}
        public boolean retainAll(Collection<?> c)   {return s.retainAll(c);}
        // addAll is the only inherited implementation
        
    }

    結(jié)語(yǔ)

    至此深入Java集合框架(Java Collections Framework Internals)系列已經(jīng)全部講解完畢,希望這幾篇簡(jiǎn)短的博文能夠幫助各位讀者對(duì)Java容器框架建立基本的理解。通過(guò)這里可以返回本系列文章目錄

    如果對(duì)各位有哪怕些微的幫助,博主將感到非常高興!如果博文中有任何的紕漏和謬誤,歡迎各位博友指正。

    本文GitHub地址

    posted on 2016-05-31 07:27 CarpenterLee 閱讀(1119) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲色大成网站www永久男同| 中文字幕永久免费| 亚洲精品无码专区久久同性男| 久久久久噜噜噜亚洲熟女综合 | 亚洲精品亚洲人成在线麻豆| 97在线免费视频| 亚洲午夜久久久久妓女影院| 美女内射毛片在线看免费人动物| 久久久久亚洲Av无码专| 国内外成人免费视频| 国产成人精品久久亚洲高清不卡| 国产亚洲AV夜间福利香蕉149 | 99热这里只有精品6免费| 亚洲国产精品久久久久婷婷软件| 成人特黄a级毛片免费视频| a级毛片毛片免费观看永久| 亚洲一区二区三区高清不卡| 午夜成人免费视频| 美女被羞羞网站免费下载| 精品亚洲国产成AV人片传媒| 亚洲AⅤ无码一区二区三区在线| **一级毛片免费完整视| 国产精品综合专区中文字幕免费播放| 夜夜嘿视频免费看| 95老司机免费福利| 黄视频在线观看免费| 精品韩国亚洲av无码不卡区| 亚洲综合激情九月婷婷| 国内精品99亚洲免费高清| 永久黄网站色视频免费| 免费人成在线观看69式小视频| 二个人看的www免费视频| 色天使色婷婷在线影院亚洲| 亚洲图片激情小说| 亚洲成年人在线观看| 成人毛片18女人毛片免费| 99热在线观看免费| 久久免费高清视频| 一个人看的免费视频www在线高清动漫| 久久精品国产精品亚洲艾| 我想看一级毛片免费的|