最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java?Map中三個冷門容器的使用

 更新時間:2022年12月12日 08:20:39   作者:JAVA旭陽  
本篇文章主要講解下Map家族中3個相對冷門的容器,分別是WeakHashMap、EnumMap、IdentityHashMap,?想必大家在平時的工作中也很少用到,或者壓根不知道他們的特性以及適用場景,本篇文章就帶你一探究竟

概述

本篇文章主要講解下Map家族中3個相對冷門的容器,分別是WeakHashMap、EnumMap、IdentityHashMap, 想必大家在平時的工作中也很少用到,或者壓根不知道他們的特性以及適用場景,本篇文章就帶你一探究竟。

WeakHashMap

介紹

WeakHashMap稱為弱三列映射,實現(xiàn)了Map接口,具有如下特性:

  • WeakHashMap中的entry是一個弱引用,當除了自身有對key的引用外,此key沒有其他引用,那么GC之后此map會自動丟棄此值。
  • 不是線程安全的
  • 可以存儲null

演示案例

  public static void main(String[] args) {
        String a = new String("a");
        String b = new String("b");
        Map weakmap = new WeakHashMap();
        weakmap.put(a, "aaa");
        weakmap.put(b, "bbb");
        a = null;
        b = null;
        // 進行g(shù)c
        System.gc();
        Iterator j = weakmap.entrySet().iterator();
        while (j.hasNext()) {
            Map.Entry en = (Map.Entry) j.next();
            System.out.println("weakmap:" + en.getKey() + ":" + en.getValue());
        }
    }

運行結(jié)果:

已經(jīng)被gc回收了。

原理實現(xiàn)

從這里我們可以看到其內(nèi)部的Entry繼承了WeakReference,也就是弱引用,所以就具有了弱引用的特點。

弱引用的特點是在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象,不管當前內(nèi)存空間足夠與否,都會回收它的內(nèi)存。不過,由于垃圾回收器是一個優(yōu)先級很低的線程,因此不一定會很快發(fā)現(xiàn)那些只具有弱引用的對象。

WeakReference中有個成員變量ReferenceQueue,他的作用是GC會清理掉對象之后,引用對象會被放到ReferenceQueue中,然后遍歷這個queue進行刪除即可Entry。WeakHashMap內(nèi)部有一個expungeStaleEntries函數(shù),在這個函數(shù)內(nèi)部實現(xiàn)移除其內(nèi)部不用的entry從而達到的自動釋放內(nèi)存的目的。因此我們每次訪問WeakHashMap的時候,都會調(diào)用這個expungeStaleEntries函數(shù)清理一遍。

使用場景

在如今的并發(fā)泛濫的大環(huán)境下,大家應該都用過緩存,緩存都是放在內(nèi)存中的,而內(nèi)存幾乎是計算機中最寶貴也是最稀缺的資源,所以需要謹慎的使用,不然很容易就出現(xiàn) OOM。緩存的主要作用是為了更快的處理業(yè)務(wù)、降低服務(wù)器的壓力,那么就要保證緩存命中率,這里假設(shè)整個緩存是一個 key-value 結(jié)構(gòu)的(以鍵值對緩存為例),HashMap 作為強引用對象在沒有主動將 key 刪除時是不會被 JVM 回收的,這樣 HashMap 中的對象就會越積越多直到 OOM 錯誤;那么如何做到既讓緩存的命中率高又不占用那么多的內(nèi)存,這里就可以采用 WeakHashMap,當然不會有 HashMap 100% 的命中率(假設(shè)內(nèi)存足夠),但是在保證程序正常的前提下更好的實現(xiàn)了緩存這套解決方案。

EnumMap

介紹

用于枚舉類型鍵的專用Map實現(xiàn)。枚舉映射中的所有鍵必須來自創(chuàng)建映射時顯式或隱式指定的單個枚舉類型。

相對于HashMap中枚舉作為key, EnumMap內(nèi)部以一個非常緊湊的數(shù)組存儲value,并且根據(jù)enum類型的key直接定位到內(nèi)部數(shù)組的索引,并不需要計算hashCode(),不但效率最高,而且沒有額外的空間浪費。

  • 不是線程安全的
  • 可以存放null值

演示案例

public static void main(String[] args) {
        // 構(gòu)造函數(shù)傳入類型
        Map<DayOfWeek, String> map = new EnumMap<>(DayOfWeek.class);
        map.put(DayOfWeek.MONDAY, "星期一");
        map.put(DayOfWeek.TUESDAY, "星期二");
        map.put(DayOfWeek.WEDNESDAY, "星期三");
        map.put(DayOfWeek.THURSDAY, "星期四");
        map.put(DayOfWeek.FRIDAY, "星期五");
        map.put(DayOfWeek.SATURDAY, "星期六");
        map.put(DayOfWeek.SUNDAY, "星期日");
        System.out.println(map);
        System.out.println(map.get(DayOfWeek.MONDAY));
    }

    enum DayOfWeek {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }

原理實現(xiàn)

put方法源碼如下:

 public V put(K key, V value) {
        // 對枚舉類型進行檢查,看key和構(gòu)造函數(shù)傳入的class類型是否一致
        typeCheck(key);
        // 枚舉的順序
        int index = key.ordinal();
        // 原來位置的值
        Object oldValue = vals[index];
        // 設(shè)置值
        vals[index] = maskNull(value);
        if (oldValue == null)
            size++;
        return unmaskNull(oldValue);
    }

通過put源碼發(fā)現(xiàn)是通過數(shù)組的方式實現(xiàn)存儲,而且也不需要進行擴容。

使用場景

如果項目中遇到針對枚舉作為key的映射容器,可以優(yōu)先選擇EnumMap。

IdentityHashMap

介紹

該類使用散列表實現(xiàn)Map接口,在比較鍵(和值)時使用引用相等代替對象相等。換句話說,在一個IdentityHashMap中,當且僅當(k1k2)兩個鍵k1和k2被認為是相等的。(在正常的Map實現(xiàn)(如HashMap)兩個鍵k1和k2被認為是相等的,當且僅當(k1null ?k2 = = null: k1.equals (k2)))。

  • 不是線程安全的
  • 無序
  • key不可以是null

演示案例

public static void main(String[] args) {
        // hashMap
        Map<Integer, String> hashMap = new HashMap<>();
        // identityHashMap
        Map<Integer, String> identityHashMap = new IdentityHashMap<>();

        hashMap.put(new Integer(200), "a");
        hashMap.put(new Integer(200), "b");
        identityHashMap.put(new Integer(200), "a");
        identityHashMap.put(new Integer(200), "b");

        //遍歷hashmap
        System.out.println("hashmap 結(jié)果:");
        hashMap.forEach((key, value) -> {
            System.out.println("key = " + key + ", value = " + value);
        });

        //遍歷hashmap
        System.out.println("identityHashMap 結(jié)果:");
        identityHashMap.forEach((key, value) -> {
            System.out.println("key = " + key + ", value = " + value);
        });

    }

運行結(jié)果:

原理實現(xiàn)

IdentityHashMap底層的數(shù)據(jù)結(jié)構(gòu)就是數(shù)組,我們關(guān)注下put方法:

調(diào)用hash方法,獲取key在table的位置index,然后進行賦值操作,也是分成了3種情況:

1.item == k,找到了對應的key,value存在key右相鄰的位置,對tab[i + 1]進行更新,并返回原來的值;

2.item == null,表示table中沒有對應的key值,跳出for循環(huán),執(zhí)行tab[i] = k和tab[i + 1] = value進行新key的插入操作。個人覺得這里的擴容時機選擇的不太好,好不容易找到的更新位置,因為擴容給整沒了,還得再次重新計算,可以和HashMap一樣,在更新后再擴容。

3.item != null && item != key,表示hash沖突發(fā)生,調(diào)用nextKeyIndex獲取處理沖突后的index位置,然后重復上面的過程。

我們再來看下hash方法:

IdentityHashMap中獲取hash值采用的System.identityHashCode方法,在不重寫Object.hashCode方法時,System.identityHashCode和Object.hashCode返回的值相同,相當于對象的唯一的HashCode。System.identityHashCode(null)始終返回0, 無論是否重寫Object.hashCode,都不影響System.identityHashCode的執(zhí)行結(jié)果。

使用場景

當我們必須使用地址相等來判斷值相等的場合,以及我們確定只要其地址不相等,則其equals方法的結(jié)果也必定不相等的場合。

到此這篇關(guān)于詳解Java Map中三個冷門容器的使用的文章就介紹到這了,更多相關(guān)Java Map容器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java隱藏特性之雙括號初始化詳解

    Java隱藏特性之雙括號初始化詳解

    Java?語言擁有許多隱藏而強大的特性,其中之一是雙括號初始化,這篇文章將詳細介紹雙括號初始化的概念、用法和示例代碼,希望對大家有所幫助
    2023-12-12
  • 使用Java實現(xiàn)加密之AES加解密

    使用Java實現(xiàn)加密之AES加解密

    這篇文章主要介紹了使用Java實現(xiàn)加密之AES加解密,AES為最常見的對稱加密算法,對稱加密算法也就是加密和解密用相同的密鑰,需要的朋友可以參考下
    2023-05-05
  • mybatis-plus開啟sql打印的三種方式總結(jié)

    mybatis-plus開啟sql打印的三種方式總結(jié)

    這篇文章主要給大家介紹了mybatisplus開啟sql打印的三種方式,文章通過代碼示例介紹的非常詳細,對大家的學習或工作有一定的參考價值,需要的朋友可以參考下
    2023-11-11
  • Javaweb mybatis接口開發(fā)實現(xiàn)過程詳解

    Javaweb mybatis接口開發(fā)實現(xiàn)過程詳解

    這篇文章主要介紹了Javaweb mybatis接口開發(fā)實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • Java中調(diào)用SQL Server存儲過程詳解

    Java中調(diào)用SQL Server存儲過程詳解

    這篇文章主要介紹了Java中調(diào)用SQL Server存儲過程詳解,本文講解了使用不帶參數(shù)的存儲過程、使用帶有輸入?yún)?shù)的存儲過程、使用帶有輸出參數(shù)的存儲過程、使用帶有返回狀態(tài)的存儲過程、使用帶有更新計數(shù)的存儲過程等操作實例,需要的朋友可以參考下
    2015-01-01
  • Java String類字符串的理解與認知

    Java String類字符串的理解與認知

    String字符串和char字符不同,char使用單引號,只能表示一個字符,字符串就是一段文本。String是個類。這個類使用final修飾,所以這個類是不可以繼承擴充和修改它的方法的
    2021-10-10
  • Java?Lambda表達式常用的函數(shù)式接口

    Java?Lambda表達式常用的函數(shù)式接口

    這篇文章主要介紹了Java?Lambda表達式常用的函數(shù)式接口,文章基于Java?Lambda表達式展開對常用的函數(shù)式接口的介紹,具有一的的參考價值需要的小伙伴可以參考一下
    2022-04-04
  • SpringBoot通過@Scheduled實現(xiàn)定時任務(wù)及單線程運行問題解決

    SpringBoot通過@Scheduled實現(xiàn)定時任務(wù)及單線程運行問題解決

    Scheduled定時任務(wù)是Spring boot自身提供的功能,所以不需要引入Maven依賴包,下面這篇文章主要給大家介紹了關(guān)于SpringBoot通過@Scheduled實現(xiàn)定時任務(wù)以及問題解決的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Java面試題沖刺第二十八天--數(shù)據(jù)庫(5)

    Java面試題沖刺第二十八天--數(shù)據(jù)庫(5)

    這篇文章主要為大家分享了最有價值的三道關(guān)于數(shù)據(jù)庫的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 詳解JSON與?Java對象之間的轉(zhuǎn)化

    詳解JSON與?Java對象之間的轉(zhuǎn)化

    在現(xiàn)在的日常開發(fā)中,不管前端還是后端,JSON?格式的數(shù)據(jù)是用得比較多的,甚至可以說無處不在。所以本文主要來講講JSON?格式的數(shù)據(jù)與?Java?對象之間的轉(zhuǎn)化吧
    2023-03-03

最新評論

金湖县| 清河县| 云浮市| 申扎县| 邵阳县| 江达县| 伊春市| 贺州市| 甘泉县| 油尖旺区| 德安县| 镇雄县| 绥中县| 濮阳市| 定南县| 岳池县| 郓城县| 化州市| 新平| 育儿| 定兴县| 巩留县| 台东市| 吉水县| 巴彦淖尔市| 大厂| 湖南省| 彭州市| 商水县| 彰化市| 武定县| 彰武县| 曲水县| 昌邑市| 开封市| 乌鲁木齐市| 胶南市| 龙海市| 井冈山市| 伊吾县| 赤峰市|