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

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

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

    王胖子.奮斗();

    王胖子的黑板報(bào)
    posts - 0, comments - 6, trackbacks - 0, articles - 1

    人物:

    王小胖:性別:男。程序員,工作經(jīng)驗(yàn)1 year。愛好:吃肉、電玩、馬小花。特技:吃肉不用考慮胃的容量。

    馬小花:性別:女。學(xué)生,工作經(jīng)驗(yàn)0 year。愛好:蛋糕、臭美、王小胖。特技:能夠降服王小胖……

     

    /**20112月,電影《將愛情進(jìn)行到底》火得不得了。周末,小胖也陪著小花去看這部電影。放映中,小花被影片中的靖哥哥和杜拉拉感動(dòng)的一沓糊涂,而小胖則心里暗自后悔沒有買一袋大爆米花來打發(fā)這無(wú)聊的時(shí)間。影片結(jié)束,小花已經(jīng)是鼻涕一把淚一把,小胖也只有裝模作樣地抽動(dòng)了幾下鼻子,一心只想著一會(huì)兒是吃麥當(dāng)勞還是必勝客。*/

    回到家中,小胖和小花各自玩著電腦。

    小花:胖子,你知道HashtableHashMap的區(qū)別嗎?

    小胖:略知。

    小花:……裝什么!!給我講講!!!

    小胖:好的……

    第一個(gè)區(qū)別就先來說說繼承關(guān)系吧。

     如果你在baidu里google一下(技術(shù)類文章的搜索還是推薦google),會(huì)發(fā)現(xiàn)網(wǎng)上的大致說法與“由于Java發(fā)展的歷史原因。Hashtable是基于陳舊的Dictionary類的,HashMap是Java 1.2引進(jìn)的Map接口的一個(gè)實(shí)現(xiàn)。”相同。這種說法沒有錯(cuò),但是胖子覺得不夠準(zhǔn)確,特別是對(duì)于我們這種大眾菜鳥來說,如果不去深究的話,可能就會(huì)造成一些理解上的差異。簡(jiǎn)單的認(rèn)為Hashtable沒有繼承Map接口。胖子之前就犯過這樣的錯(cuò)誤(胖子承認(rèn)自己笨,是真笨……) 。

           小花:那你怎么知道它們兩個(gè)各自的繼承關(guān)系呢?胖子。

    我們可以參考一下最新的JDK1.6的源碼,看看這兩個(gè)類的定義:


    public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {…}
    public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {…}



    可以看到hashtable也是繼承了Map接口。它們的不同是Hashtable(since JDK1.0)就繼承了Dictionary這個(gè)抽象類,而HashMap(since JDK1.2)繼承的則是AbstractMap這個(gè)抽象類。因?yàn)樵贖ashtable中看到繼承Map后所實(shí)現(xiàn)的方法是JDK1.2版本時(shí)加上去的,所以胖子猜想可能是在JDK 1.2開發(fā)時(shí)Sun工程師出于統(tǒng)一的考慮使得Hashtable也繼承了Map接口。

           小花:哦,原來JDK源碼還能看出來這個(gè)。

           小胖:……后面還能看出更多東西的。

           小花:好期待啊。


    第二個(gè)區(qū)別我們從同步和并發(fā)性上來說說它們兩個(gè)的不同。


    可以通過這兩個(gè)類得源碼來分析,Hashtable中的主要方法都做了同步處理,而HashMap則沒有。可以說Hashtable在默認(rèn)情況支持同步,而HashMap在默認(rèn)情況下是不支持的。我們?cè)诙嗑€程并發(fā)的環(huán)境下,可以直接使用Hashtable,但是要使用HashMap的話就要自己增加同步處理了。對(duì)HashMap的同步處理可以使用Collections類提供的synchronizedMap靜態(tài)方法;或者直接使用JDK5.0之后提供的java.util.concurrent包里的ConcurrentHashMap類。

    小胖:synchronizedMap靜態(tài)方法和ConcurrentHashMap類我會(huì)以后再給你詳細(xì)講一下的。肥婆。

    小花:你保證啊。鑰匙忘了你知道后果的。

    小胖:好的……


    第三個(gè)區(qū)別就是它們對(duì)于null值的處理方式了。


    我們依然能夠從源代碼中得知,Hashtable中,key和value都不允許出現(xiàn)null值。


    public synchronized V put(K key, V value) {
    // Make sure the value is not null
    if (value == null) {
    throw new NullPointerException();
    }
    // Makes sure the key is not already in the hashtable.
    Entry tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    //…
    }
      

    在我們使用上面的方法時(shí),如參數(shù)value為null,可以從代碼中直接看出程序會(huì)拋出NullPointerException;而在key為null時(shí),則會(huì)在“int hash = key.hashCode();“這段計(jì)算Hash值的過程中拋出NullPointerException。而在在HashMap中,允許null作為key存在,并且和其他key的特性一樣,這樣的null值key只能有一個(gè);另外HashMap允許多個(gè)value為null。這樣大家就要注意了, HashMap中就不能用get(key)方法來判斷HashMap中是否存在某個(gè)key,因?yàn)関alue為null和不存在該key的Entry都會(huì)返回null值,而應(yīng)該用containsKey()方法來判斷了。


    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    public class TestCase {
    public static void main(String[] args) {
    Map<Integer,String> hashMap = new HashMap<Integer,String>();
    hashMap.put(0, null);
    hashMap.put(1, "one");
    hashMap.put(2, "two");
    hashMap.put(null, "null");
    for(Entry<Integer, String> e : hashMap.entrySet()) {
    System.out.println("Key: " + e.getKey() + " -- Value: " + e.getValue());
    }
    System.out.println(hashMap.get(0));
    System.out.println(hashMap.get(4));
    System.out.println("Contains key 0 ? :" + hashMap.containsKey(0));
    System.out.println("Contains key 4 ? :" + hashMap.containsKey(4));
    System.out.println("Contains value null ? :" + hashMap.containsValue(null));
    }
    }
     

    結(jié)果:


    Key: null -- Value: null
    Key: 0 -- Value: null
    Key: 1 -- Value: one
    Key: 2 -- Value: two
    null
    null
    Contains key 0 ? :true
    Contains key 4 ? :false
    Contains value null ? :true


    HashMap對(duì)于null值key的處理網(wǎng)上有說“null 用new Object()來代替,其Entry.hashCode=0,而且在取出的時(shí)候還會(huì)還回null的。”胖子我在讀取源碼的過程中看到了null值的hash值確實(shí)是0 (內(nèi)部實(shí)現(xiàn)的數(shù)組中的index也是),但是能力有限沒有看到轉(zhuǎn)為new Object()的過程。

    小花: 原來hashMapcontainsKey還有這么個(gè)陷阱,以后肥婆要小心了。

    第四個(gè)不同就是它們兩個(gè)Hash值的獲取方式了。


    還是通過源代碼源代碼,Hashtable是直接使用key對(duì)象的hash值。



    public synchronized V put(K key, V value) {
    // Make sure the value is not null
    if (value == null) {
    throw new NullPointerException();
    }
    // Makes sure the key is not already in the hashtable.
    Entry tab[] = table;
    int hash = key.hashCode();//hashcode
    int index = (hash & 0x7FFFFFFF) % tab.length;
    //…
    }
     


    而HashMap則是利用key對(duì)象的hash值重新計(jì)算一個(gè)新的hash值。



    public V put(K key, V value) {
    if (key == null)
    return putForNullKey(value);
    int hash = hash(key.hashCode());//hashcode
    int i = indexFor(hash, table.length);
    //…
    }
    static int hash(int h) {
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
    }


    小花:胖子,都用了hash算法,你給我講講Hash算法吧。

    小胖:嗯……以后的,今天我比較忙(其實(shí)是不會(huì))。

    小花:你是不是不會(huì)啊?嘿嘿(壞笑)。

    小胖:什么不會(huì)……談下一話題……

     

    第五個(gè)不同就是HashtableHashMap它們兩個(gè)內(nèi)部實(shí)現(xiàn)方式的數(shù)組的初始大小和擴(kuò)容的方式。


    HashMap中內(nèi)部數(shù)組的初始容量是16, 加載因子為0.75,而且數(shù)組容量增容后也要是2指數(shù)次冪:



    /**
    * The default initial capacity - MUST be a power of two.
    */
    static final int DEFAULT_INITIAL_CAPACITY = 16;
    /**
    * The load factor used when none specified in constructor.
    */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
     


    HashTable中的內(nèi)部數(shù)組的初始容量是11,加載因子也是0.75數(shù)組的增容方式為(oldCapacity * 2 + 1):



    public Hashtable() {
    this(11, 0.75f);
    }
    protected void rehash() {
    int oldCapacity = table.length;
    Entry[] oldMap = table;
    int newCapacity = oldCapacity * 2 + 1;
    //…
    }
     


    第六個(gè)不同我們從它們兩個(gè)遍歷方式的內(nèi)部實(shí)現(xiàn)上來說。

    Hashtable HashMap都使用了 Iterator。而由于歷史原因,Hashtable還使用了Enumeration的方式 。

    小花:IteratorEnumeration的區(qū)別是什么啊?給我講講。

    小胖:我不是說我沒有時(shí)間嘛,下回的。

    小花:我都記下來,省得你給我混過去。(拿起筆開始記賬中)

    小胖:……(緊張)

    第七個(gè)不同時(shí)它們的拷貝構(gòu)造函數(shù)的不同。


    依然是通過查看源碼,可以發(fā)現(xiàn)它們兩個(gè)對(duì)于拷貝函數(shù)初始容量的不同值。

    HashMap的實(shí)現(xiàn)是:



    public HashMap(Map<? extends K, ? extends V> m) {
    this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
    DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
    putAllForCreate(m);
    }
     


    而Hashtable的實(shí)現(xiàn)是:



    public Hashtable(Map<? extends K, ? extends V> t) {
    this(Math.max(2*t.size(), 11), 0.75f);
    putAll(t);
    }
     



    小胖:今天講的已經(jīng)很多了。我有點(diǎn)餓了,肥婆。

    小花:看你今天的表現(xiàn)這么好。走,帶你去吃烤肉去。

    小胖:哈哈,肥婆萬(wàn)歲。


    PS:下面打算寫的一些東西



    1. TreeMap的排序及其他相關(guān)集合類
    2. synchronizedMap的使用方式
    3. concurrentMap實(shí)現(xiàn)細(xì)節(jié)和使用
    4. Properties使用說明和 擴(kuò)展
    5. Iterator和Enumeration的區(qū)別
    6. Hash算法 的實(shí)現(xiàn) 

    Feedback

    # re: Hashtable和HashMap引發(fā)的血案  回復(fù)  更多評(píng)論   

    2011-02-28 09:09 by 窩窩影視
    留個(gè)言 然后仔細(xì)看

    # re: Hashtable和HashMap引發(fā)的血案[未登錄]  回復(fù)  更多評(píng)論   

    2011-02-28 13:34 by roger
    寫的蠻有趣的!不錯(cuò)
    能否留個(gè)聯(lián)系方式,我們聊聊

    # re: Hashtable和HashMap引發(fā)的血案  回復(fù)  更多評(píng)論   

    2011-02-28 15:19 by 王胖子
    @窩窩影視
    謝謝支持 :)

    # re: Hashtable和HashMap引發(fā)的血案  回復(fù)  更多評(píng)論   

    2011-02-28 15:22 by 王胖子
    @roger
    呵呵 謝謝你的夸獎(jiǎng)。我的QQ:61493759(驗(yàn)證:blogjava)。有時(shí)間大家交個(gè)朋友,共同學(xué)習(xí)。

    # re: Hashtable和HashMap引發(fā)的血案[未登錄]  回復(fù)  更多評(píng)論   

    2011-02-28 18:49 by NOHI
    O

    # re: Hashtable和HashMap引發(fā)的血案[未登錄]  回復(fù)  更多評(píng)論   

    2011-03-02 10:55 by xylz
    寫的不錯(cuò),支持原創(chuàng)的

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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 免费在线观看自拍性爱视频| 猫咪免费人成在线网站| 亚洲不卡AV影片在线播放| 88xx成人永久免费观看| 窝窝影视午夜看片免费| 亚洲综合久久精品无码色欲| 青青草原精品国产亚洲av| 亚洲午夜久久久久妓女影院 | 国产麻豆免费观看91| 99爱在线精品视频免费观看9 | 亚洲无av在线中文字幕| 国产午夜鲁丝片AV无码免费| 欧洲精品成人免费视频在线观看| 91香蕉国产线在线观看免费| 久久免费国产视频| 青青操视频在线免费观看| 偷自拍亚洲视频在线观看| 在线观看亚洲AV日韩AV| 国产成人午夜精品免费视频| 国产黄在线播放免费观看| 蜜桃传媒一区二区亚洲AV| 亚洲自国产拍揄拍| 久久亚洲sm情趣捆绑调教| 亚洲av日韩av无码黑人| 亚洲精品白浆高清久久久久久| 亚洲片国产一区一级在线观看| 免费永久在线观看黄网站| 成年女人男人免费视频播放| 99精品全国免费观看视频| 在线观看的免费网站| 中字幕视频在线永久在线观看免费 | 亚洲AV永久无码精品网站在线观看| 456亚洲人成影院在线观| 亚洲av成人综合网| ass亚洲**毛茸茸pics| 亚洲mv国产精品mv日本mv| 亚洲三级中文字幕| 亚洲国产成人久久精品大牛影视 | 白白国产永久免费视频| 国产精品久久香蕉免费播放| 免费永久在线观看黄网站|