JAVA學(xué)習(xí)-Map詳解

1.介紹

Map接口定義了一個(gè)保存key-value的對象,該對象中key值是不存在重復(fù)的,每個(gè)key值至多對應(yīng)一個(gè)value
在前面幾篇的文章中分別介紹了Map的實(shí)現(xiàn)類壕鹉,如HashMap、Hashtable聋涨、TreeMap晾浴,詳細(xì)可以查看

2.類圖結(jié)構(gòu)

Map結(jié)構(gòu)

如上圖所示是實(shí)現(xiàn)Map接口的類圖結(jié)構(gòu),主要包含了如下的類與接口:

  • Map接口: 定義將鍵值映射到值的對象牍白,Map規(guī)定不能包含重復(fù)的鍵值脊凰,每個(gè)鍵最多可以映射一個(gè)值,這個(gè)接口是用來替換Dictionary類。
  • SortedMap接口:定義按照key排序的Map結(jié)構(gòu)茂腥,規(guī)定key-value是根據(jù)鍵key值的自然排序進(jìn)行排序的笙各,或者根據(jù)構(gòu)造key-value時(shí)設(shè)定的構(gòu)造器進(jìn)行排序。
  • NavigableMap接口: 是SortedMap接口的子接口础芍,在其基礎(chǔ)上擴(kuò)展了針對搜索目標(biāo)返回最近匹配項(xiàng)的導(dǎo)航方法杈抢,例如方法lowEntry、floorEntry仑性、ceilingEntry等惶楼,如果不存在這樣的鍵,則返回null
  • AbstractMap類:提供了一個(gè)Map骨架的實(shí)現(xiàn),盡量減少了實(shí)現(xiàn)Map接口所需要的工作量
  • HashMap類:HashMap是實(shí)現(xiàn)了Map接口的key-value集合诊杆,實(shí)現(xiàn)了所有map的操作歼捐,允許key和value為null,它相當(dāng)于Hashtable,與之存在的區(qū)別是hashMap不是線程安全的晨汹,HashMap允許null值豹储。
  • TreeMap類:TreeMap是基于紅黑樹的實(shí)現(xiàn),也是記錄了key-value的映射關(guān)系淘这,該映射根據(jù)key的自然排序進(jìn)行排序或者根據(jù)構(gòu)造方法中傳入的比較器進(jìn)行排序剥扣,也就是說TreeMap是有序的key-value集合
  • Hashtable類:它是類似與HashMap的key-value的哈希表,不允許key-value為NULL值铝穷,另外一點(diǎn)值得注意的是Hashtable是線程安全的
  • Serializable接口:實(shí)現(xiàn)了該接口標(biāo)識了類可以被序列化和反序列化钠怯,具體的 查詢序列化詳解
  • Cloneable接口:實(shí)現(xiàn)了該接口的類可以顯示的調(diào)用Object.clone()方法,合法的對該類實(shí)例進(jìn)行字段復(fù)制曙聂,如果沒有實(shí)現(xiàn)Cloneable接口的實(shí)例上調(diào)用Obejct.clone()方法晦炊,會(huì)拋出CloneNotSupportException異常。正常情況下,實(shí)現(xiàn)了Cloneable接口的類會(huì)以公共方法重寫Object.clone()

3.比較

雖然HashMap断国、Hashtable贤姆、TreeMap這三個(gè)都是Map接口的實(shí)現(xiàn),其內(nèi)部實(shí)現(xiàn)及性能等還是存在區(qū)別稳衬,下面將從區(qū)別及性能兩個(gè)方面去分析庐氮。

3.1 區(qū)別

3.1.1 基本
  • HashMap:初始化容量為16,擴(kuò)容每次為2*oldCap,key-value可以為NULL值
  • Hashtable:初始化容量為11宋彼,擴(kuò)容每次為2*oldCap+1,key-value不可以為NULL值
  • TreeMap:初始化容量為0弄砍,內(nèi)部是紅黑樹結(jié)構(gòu),不存在hash沖突的情況输涕,不存在擴(kuò)容的操作,key-value不可以為NULL值
3.1.2 實(shí)現(xiàn)
  • HashMap:實(shí)現(xiàn)了Map接口音婶,繼承了AbstractMap類
  • Hashtable:實(shí)現(xiàn)了Map接口,繼承了AbstractMap類
  • TreeMap:由于TreeMap是有序的莱坎,所以其除了實(shí)現(xiàn)了Map接口衣式,還實(shí)現(xiàn)了SortedMap、NavigableMap接口
3.1.3 內(nèi)部原理
  • HashMap:HashMap是散列表實(shí)現(xiàn)檐什,內(nèi)部是數(shù)組+鏈表或者紅黑樹的結(jié)構(gòu)
  • Hashtable:Hashtable也是散列表實(shí)現(xiàn)碴卧,內(nèi)部是數(shù)組+鏈表的結(jié)構(gòu)
  • TreeMap:TreeMap內(nèi)部是紅黑樹的結(jié)構(gòu)
3.1.4 線程安全
  • HashMap:不是線程安全的,其實(shí)通過Map m = Collections.synchronizeMap(hashMap)的方式也可以使得HashMap變成線程安全的乃正,但是這樣做對程序的性能可能是噩夢住册,在后面會(huì)介紹ConcurrentHashMap,建議在多線程的情況下可以使用ConcurrentHashMap替換HashMap.
  • Hashtable:是線程安全的瓮具,內(nèi)部方法使用關(guān)鍵字synchronized修飾
  • TreeMap:不是線程安全的

3.2 性能

按照如下代碼對HashMap荧飞、Hashtable、TreeMap的性能進(jìn)行測試

public class HashMapProgress {
    //定義用于測試的HashMap
    private static HashMap<Integer,Integer> hashMap = new HashMap<>();
    //定義用于測試的Hashtable
    private static Hashtable<Integer,Integer> hashtable = new Hashtable<>();
    //定義用于測試的TreeMap
    private static TreeMap<Integer,Integer> treeMap = new TreeMap<>();

    /**
     * 添加元素的方法
     * @param map 對應(yīng)的map
     * @param count 添加個(gè)數(shù)
     */
    public static void addEntry(Map<Integer,Integer> map, int count){
        Long startTime = System.currentTimeMillis();
        if (count <= 0){
            return;
        }
        for (int i = 0; i < count; i++) {
            map.put(i,i);
        }
        Long endTime = System.currentTimeMillis();
        System.out.println("添加(" + count + ")個(gè)元素使用時(shí)間:" + (endTime - startTime) + "s");
    }

    /**
     * 獲取元素的方法
     * @param map
     * @param count
     */
    public static void getEntry(Map<Integer,Integer> map, int count){
        Long startTime = System.currentTimeMillis();
        if (count <= 0){
            return;
        }
        for (int i = 0; i < count; i++) {
            map.get(i);
        }
        Long endTime = System.currentTimeMillis();
        System.out.println("獲取(" + count + ")個(gè)元素使用時(shí)間:" + (endTime - startTime) + "s");
    }

    public static void main(String[] args){
        System.out.println("-------HashMap測試開始-----");
        addEntry(hashMap,1000000);
        getEntry(hashMap,1000000);
        System.out.println("-------HashMap測試結(jié)束-----");

        System.out.println("-------Hashtable測試開始-----");
        addEntry(hashtable,1000000);
        getEntry(hashtable,1000000);
        System.out.println("-------Hashtable測試結(jié)束-----");

        System.out.println("-------TreeMap測試開始-----");
        addEntry(treeMap,1000000);
        getEntry(treeMap,1000000);
        System.out.println("-------TreeMap測試結(jié)束-----");
    }
}

分別測試了100000,1000000,10000000個(gè)數(shù)據(jù)的情況名党,測試結(jié)果如下所示:

數(shù)據(jù)量 HashMap Hashtable TreeMap
100000 插入用時(shí):18s 查詢用時(shí):9s 插入用時(shí):14s 查詢用時(shí):5s 插入用時(shí):33s 查詢用時(shí):17s
1000000 插入用時(shí):98s 查詢用時(shí):20s 插入用時(shí):625s 查詢用時(shí):31s 插入用時(shí):242s 查詢用時(shí): 145s
10000000 插入用時(shí):9773s 查詢用時(shí):811s 插入用時(shí):15055s 查詢用時(shí):3369s 插入用時(shí):22354s 查詢用時(shí): 3889s

通過上表可以看出隨著數(shù)據(jù)量的增加叹阔,時(shí)間變化差異還是很大的,而在單線程的情況下還是盡量使用HashMap传睹,相對于Hashtable耳幢、TreeMap性能更好,而針對特定的情況需視情況而論欧啤。

4.總結(jié)

本文主要是對前面介紹的HashMap睛藻、Hashtable、TreeMap這些Map接口實(shí)現(xiàn)類的一個(gè)總結(jié)堂油,主要分析這些實(shí)現(xiàn)類的一些特點(diǎn)以及存在的差異修档,最后想說的是針對不同的情況可以選擇不同的Map進(jìn)行編碼碧绞,如有問題府框,望指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市迫靖,隨后出現(xiàn)的幾起案子院峡,更是在濱河造成了極大的恐慌,老刑警劉巖系宜,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件照激,死亡現(xiàn)場離奇詭異,居然都是意外死亡盹牧,警方通過查閱死者的電腦和手機(jī)俩垃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汰寓,“玉大人口柳,你說我怎么就攤上這事∮谢” “怎么了跃闹?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長毛好。 經(jīng)常有香客問我望艺,道長,這世上最難降的妖魔是什么肌访? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任找默,我火速辦了婚禮,結(jié)果婚禮上吼驶,老公的妹妹穿的比我還像新娘啡莉。我一直安慰自己,他們只是感情好旨剥,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布咧欣。 她就那樣靜靜地躺著,像睡著了一般轨帜。 火紅的嫁衣襯著肌膚如雪魄咕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天蚌父,我揣著相機(jī)與錄音哮兰,去河邊找鬼。 笑死苟弛,一個(gè)胖子當(dāng)著我的面吹牛喝滞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播膏秫,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼右遭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窘哈,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤吹榴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后滚婉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體图筹,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年让腹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了远剩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骇窍,死狀恐怖民宿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情像鸡,我是刑警寧澤活鹰,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站只估,受9級特大地震影響志群,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛔钙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一锌云、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吁脱,春花似錦桑涎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至遍希,卻和暖如春等曼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凿蒜。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工禁谦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人废封。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓州泊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親漂洋。 傳聞我的和親對象是個(gè)殘疾皇子遥皂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法力喷,類相關(guān)的語法,內(nèi)部類的語法渴肉,繼承相關(guān)的語法冗懦,異常的語法爽冕,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 一颈畸、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,254評論 0 16
  • java筆記第一天 == 和 equals ==比較的比較的是兩個(gè)變量的值是否相等乌奇,對于引用型變量表示的是兩個(gè)變量...
    jmychou閱讀 1,485評論 0 3
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司眯娱,掛了不少礁苗,但最終還是拿到小米、百度徙缴、阿里试伙、京東、新浪于样、CVTE疏叨、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,192評論 11 349
  • “天真歲月不忍欺蚤蔓,青春荒唐我不負(fù)你”很喜歡《時(shí)間煮雨》這首歌中的這句話,我最愛的你們還記得嗎糊余?曾經(jīng)我們也說好要一直...
    蕊汐閱讀 446評論 0 0