Java HashMap 基礎(chǔ)

問:HashMap 中的 key 如果是 Object 則需要實現(xiàn)哪些方法?

答:hashCode 方法和 equals 方法。
因為 hashCode 方法用來計算 Entry(記錄) 在數(shù)組中的 index 索引位置,equals 方法用來比較數(shù)組指定 index 索引位置上鏈表的節(jié)點 Entry 元素是否相等。否則由于 hashCode 方法實現(xiàn)不恰當會導(dǎo)致嚴重的 hash 碰撞,從而使 HashMap 會退化成鏈表結(jié)構(gòu)而影響性能。

問:下面兩種遍歷方式有什么區(qū)別?為什么?

        //第一種 
        Map map = new HashMap();
        Iterator iter = map.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            Object key = entry.getKey();
            Object val = entry.getValue();
        }

        //第二種 
        Map map = new HashMap();
        Iterator iter = map.keySet().iterator();
        while (iter.hasNext()) {
            Object key = iter.next();
            Object val = map.get(key);
        }

答:第一種方式效率高且推薦用。
因為 HashMap 的這兩種遍歷是分別對 keySet 和 entrySet 進行迭代,對于 keySet 實質(zhì)上是遍歷了兩次,一次是轉(zhuǎn)為 iterator 迭代器遍歷,一次就從 HashMap 中取出 key 所對于的 value 操作(通過 key 值 hashCode 和 equals 索引);而 entrySet 方式只遍歷了一次,它把 key 和 value 都放到了 Entry 中,所以效率高。

問:為什么 HashMap 中 String、Integer 這樣的包裝類適合作為 key 鍵,即為什么使用它們可以減少哈希碰撞?

答:因為 String、Integer 等包裝類是 final 類型的,具有不可變性,而且已經(jīng)重寫了 equals() 和 hashCode() 方法。不可變性保證了計算 hashCode() 后鍵值的唯一性和緩存特性,不會出現(xiàn)放入和獲取時哈希碼不同的情況且讀取哈希值的高效性,此外官方實現(xiàn)的 equals() 和 hashCode() 都是嚴格遵守相關(guān)規(guī)范的,不會出現(xiàn)錯誤。

問:下面程序的輸出結(jié)果是什么?

        class Item {
            public String name;
            public int age;

            @Override
            public int hashCode() {
                return this.name.hashCode() + this.age;
            }

            public Item(String name, int age) {
                this.name = name;
                this.age = age;
            }
        }
        public class Demo {
            public static void main(String[] args) {
                Item item1 = new Item("android", 4);
                Item item2 = new Item("java", 3);
                Map<Item, Item> map = new HashMap<Item, Item>();
                map.put(item1, item1);
                map.put(item2, item2);
                item2.name = "unix c"; //相當于修改了key值
                Item value = map.get(item2);
                System.out.println("value=" + value);
            }
        }

答:輸出結(jié)果為 value=null。
因為 key 更新后 hashCode 也更新了,(這里是因為重寫了 hashcode 的原因)而 HashMap 里面的對象是我們原來哈希值的對象,在 get 時由于哈希值已經(jīng)變了,原來的對象不會被索引到了,所以結(jié)果為 null,因此當把對象放到 HashMap 后就不要嘗試對 key 進行修改操作,謹防出現(xiàn)哈希值變化或者 equals 比較不等的情況導(dǎo)致無法索引。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容