成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

你不知道的Map家族中的那些冷門容器

開發 架構
本文主要講解了集中不常用的Map, 當然我們也需要了解他們的特性,在有些時候還是會用到的。

?概述

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

WeakHashMap

介紹

WeakHashMap稱為弱三列映射,實現了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;
// 進行gc
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());
}
}

運行結果:

圖片

已經被gc回收了。

原理實現

圖片

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

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

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

圖片

使用場景

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

EnumMap

介紹

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

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

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

演示案例

public static void main(String[] args) {
// 構造函數傳入類型
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
}

原理實現

put方法源碼如下:

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

通過put源碼發現是通過數組的方式實現存儲,而且也不需要進行擴容。

使用場景

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

IdentityHashMap

介紹

該類使用散列表實現Map接口,在比較鍵(和值)時使用引用相等代替對象相等。換句話說,在一個IdentityHashMap中,當且僅當(k1==k2)兩個鍵k1和k2被認為是相等的。(在正常的Map實現(如HashMap)兩個鍵k1和k2被認為是相等的,當且僅當(k1==null ?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 結果:");
hashMap.forEach((key, value) -> {
System.out.println("key = " + key + ", value = " + value);
});

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

}

運行結果:

圖片

原理實現

IdentityHashMap底層的數據結構就是數組,我們關注下put方法:

圖片

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

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

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

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

我們再來看下hash方法:

圖片

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

使用場景

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

總結

本文主要講解了集中不常用的Map, 當然我們也需要了解他們的特性,在有些時候還是會用到的。

責任編輯:武曉燕 來源: JAVA旭陽
相關推薦

2015-06-19 13:54:49

2014-03-12 09:23:06

DevOps團隊合作

2015-10-30 09:56:10

WiFiWiFi技術傳感

2018-11-25 10:08:44

阿里巴巴技術開源

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket瀏覽器

2014-12-02 10:38:41

5G

2011-10-27 14:55:22

公有云私有云云計算

2013-09-12 14:24:31

2010-08-23 09:56:09

Java性能監控

2016-04-08 17:50:04

2011-09-15 17:10:41

2021-02-01 23:23:39

FiddlerCharlesWeb

2022-10-13 11:48:37

Web共享機制操作系統

2009-12-10 09:37:43

2020-07-29 07:37:20

Git 修復項目

2014-06-23 15:57:10

桌面系統編年史

2022-09-15 08:33:11

ChaosBladeJava場景

2013-11-12 14:50:33

2022-03-28 18:48:42

人工智能AI
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人一区二区三区在线观看 | 久久777 | 精品国产一区二区国模嫣然 | 欧美一级毛片久久99精品蜜桃 | 亚洲情侣视频 | 日韩久久网 | 欧美一区二区三区大片 | 国产精品欧美一区二区 | 亚洲国产精品网站 | 国产精品18久久久久久久 | 日韩精品免费在线观看 | 国产片网站 | 免费一级片| 欧美三级在线 | 久久久久国产一区二区 | 成人精品啪啪欧美成 | 日日碰狠狠躁久久躁婷婷 | 亚洲视频在线免费观看 | 青娱乐av | 久久久成人一区二区免费影院 | 国产精品久久久久久久久免费 | 在线a视频| 国产精品99久久久久久www | www.youjizz.com日韩| www.青娱乐 | www亚洲成人| 成人小视频在线观看 | 亚洲精品99| 免费国产成人av | 国产精品mv在线观看 | 国产一区二区三区四区区 | 精品国产91乱码一区二区三区 | 成人天堂噜噜噜 | 亚洲精品永久免费 | 国产精品毛片一区二区三区 | 国产成人综合一区二区三区 | 国内精品视频在线观看 | 精品在线一区二区三区 | 一区二区不卡 | 国产精品一区二区三区在线播放 | 亚洲精品电影在线观看 |