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

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

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

    walterwing  
    日歷
    <2008年11月>
    2627282930311
    2345678
    9101112131415
    16171819202122
    23242526272829
    30123456
    統(tǒng)計
    • 隨筆 - 12
    • 文章 - 1
    • 評論 - 7
    • 引用 - 0

    導(dǎo)航

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

     
    題目:

    public class SetSize {
        
    public static void main(string[] args) {
            Set
    <Short> set = new HashSet<Short>();
            
    for(short i = 0; i < 10; i++{
                set.add(i);
                set.remove(i 
    - 1);
            }


            System.out.println(set.size());
        }

    }

    上面代碼輸出結(jié)果為10,為什么?



    題目乍一看很簡單,不就是一個HashSet么,但看完了題目又覺得困惑:對啊,怎么會是10?真難為自己還特意花了一些時間學(xué)習(xí)Java的Collection Framework,居然連這么小的一個題目都吃不透,汗顏啊……

    看了半天,沒有思路,跳過去做其他題,待到收卷前10分鐘,不甘心,再回過頭來看這道題。發(fā)現(xiàn)一個值得懷疑的地方:Set<Short> set = ……
    為什么要特意設(shè)定是Short?再看到下面的i - 1,馬上感覺到似乎和類型轉(zhuǎn)換有關(guān)。

    目前可以肯定的是:
    1. set存儲的元素是Short類型
    2. 調(diào)用remove方法時,i - 1會自動轉(zhuǎn)型為int,也就是說,傳給remove方法的參數(shù)是一個int值

    接下來呢?int值會被自動包裝成Integer還是Short?對Java的泛型和Auto-Boxing不是很了解,于是在這犯迷糊了,只好將目前的思路草草寫了幾筆,交卷……

    作為一名后知后覺的Java愛好者,自然不能放過這么有意思的題目。如是回來之后,上機親自試驗,輸入試題程序,出來的結(jié)果果然是10(嗯,沒騙我……)。然后驗證自己的猜測:將Set<Short>改為Set<Integer>,輸出結(jié)果……1!

    看來我還是有一定的嗅覺的……

    接下來就是探索原因了

    首先驗證一下i - 1得到的結(jié)果會不會有錯:-1,0,1,……8。嗯,是對的

    然后驗證一下每次remove之后有沒有真的remove掉指定的值……發(fā)現(xiàn)沒有。

    苦思……

    經(jīng)一位精研C++的同學(xué)提醒:是不是因為存的是short,但刪的是int,所以不能刪?

    試驗一下:

    short temp = 1;
    Short s 
    = new Short(temp);  //不能是new Short(1),否則編譯出錯
    Integer i = new Integer(1);
    System.out.println(s.equals(i));

    輸出結(jié)果……false!看來終于找到真正的原因了。

    查看一下Short.equals()方法的源代碼:

    public boolean equals(Object obj) {
        
    if (obj instanceof Short) {
            
    return value == ((Short)obj).shortValue();
        }

        
    return false;
    }

    ft……居然不是同一類型的就無視……這跟胸懷廣闊的集合框架背道而馳啊……當(dāng)然,這是我的錯

    目前可以大致推斷:因為set中存入的是值為0~9的Short型對象,而每次刪除是是要求刪除值為-1~8的Integer型對象,但值相同的Short與Integer看來并不“相等”,所以無法刪除。

    那就看一下HashSet的remove方法究竟干了些什么

    public boolean remove(Object o) {
        
    return map.remove(o)==PRESENT;
    }

    public V remove(Object key) {
            Entry
    <K,V> e = removeEntryForKey(key);
            
    return (e == null ? null : e.value);
    }

    終于到主菜了……
    /**
         * Removes and returns the entry associated with the specified key
         * in the HashMap.  Returns null if the HashMap contains no mapping
         * for this key.
         
    */

        
    final Entry<K,V> removeEntryForKey(Object key) {
            
    int hash = (key == null? 0 : hash(key.hashCode());
            
    int i = indexFor(hash, table.length);
            Entry
    <K,V> prev = table[i];
            Entry
    <K,V> e = prev;

            
    while (e != null{
                Entry
    <K,V> next = e.next;
                Object k;
                
    if (e.hash == hash &&
                    ((k 
    = e.key) == key || (key != null && key.equals(k)))) {
                    modCount
    ++;
                    size
    --;
                    
    if (prev == e)
                        table[i] 
    = next;
                    
    else
                        prev.next 
    = next;
                    e.recordRemoval(
    this);
                    
    return e;
                }

                prev 
    = e;
                e 
    = next;
            }


            
    return e;
        }

    代碼就不用解釋了,大家都看得懂。

    HashSet里面刪除一個元素時,首先要根據(jù)傳進來對象的hash值從hash table中找到對應(yīng)的“Entry”,當(dāng)然,難免會有碰撞的情況,這時需要遍歷一下來找到真正需要刪除的對象。一直到這一步,Short和Integer的差異還沒有體現(xiàn)出來,因為它們返回的hash值是相同的,但當(dāng)執(zhí)行key.equals(k)的時候,就“不相等”了,因此找不到要刪除的元素,刪除失敗



    小小的一道題,囊括了Java方方面面的細節(jié),果然語言這個東西博大精深啊,有時候你以為自己很明白了,但隨便揪出一個細節(jié)來就足以打到你……

    大家還是好好學(xué)習(xí),天天向上吧
    posted on 2008-11-02 19:52 This is Wing 閱讀(644) 評論(3)  編輯  收藏 所屬分類: Java基礎(chǔ)
    評論:
    • # re: 一道小而精巧的筆試題——Set、equals、類型轉(zhuǎn)換……  sclsch Posted @ 2008-11-04 09:23
      講得不錯啊。學(xué)習(xí)了。  回復(fù)  更多評論   

    • # re: 一道小而精巧的筆試題——Set、equals、類型轉(zhuǎn)換……  sclsch Posted @ 2008-11-04 09:47
      請講講
      removeEntryForKey
      這段代碼吧,
      我是新手,看不懂。  回復(fù)  更多評論   

    • # re: 一道小而精巧的筆試題——Set、equals、類型轉(zhuǎn)換……  This is Wing Posted @ 2008-11-04 16:02
      @sclsch
      其實我建議你先去回顧一下數(shù)據(jù)結(jié)構(gòu)中的哈希表,比如怎么存儲,怎么解決碰撞,怎么查找……這些都是很基礎(chǔ)的東西,很多地方都要用到。相信當(dāng)你搞懂哈希表之后,自然也就知道上面的代碼是在做什么了  回復(fù)  更多評論   

     
    Copyright © This is Wing Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: a级毛片毛片免费观看永久| 在线综合亚洲欧洲综合网站| 乱淫片免费影院观看| 在线观看AV片永久免费| 亚洲免费视频网址| 免费观看激色视频网站(性色)| 精品亚洲成a人片在线观看| 久久午夜无码免费| 亚洲国产女人aaa毛片在线| 99re在线视频免费观看| 亚洲国产精品不卡在线电影| 免费人成在线观看网站品爱网| 亚洲AV区无码字幕中文色| 99爱在线精品视频免费观看9| 亚洲综合成人网在线观看| 91精品导航在线网址免费| 777亚洲精品乱码久久久久久 | 亚洲高清视频免费| 亚洲日韩乱码久久久久久| 日韩精品成人无码专区免费| 亚洲第一街区偷拍街拍| www亚洲精品少妇裸乳一区二区| 国产免费福利体检区久久| 亚洲AV无码久久精品成人| ww在线观视频免费观看| 亚洲欧美一区二区三区日产| 亚洲国产精品尤物yw在线| 中国一级特黄的片子免费| 噜噜噜亚洲色成人网站∨| 成人性生交大片免费看无遮挡| 国产91成人精品亚洲精品| 亚洲区小说区图片区| 日本xxxx色视频在线观看免费| 亚洲AV无码无限在线观看不卡| va亚洲va日韩不卡在线观看| 久久精品国产大片免费观看| 亚洲熟妇无码AV| 国产亚洲AV手机在线观看| 又黄又爽又成人免费视频| 尤物视频在线免费观看| 久久亚洲私人国产精品|