HashMap-----get(key)、containsKey(key)

本文基於JDK1.8

1. 註釋翻譯

    /**
     * Returns the value to which the specified key is mapped,
     * or {@code null} if this map contains no mapping for the key.
     * 返回指定的key映射的值value,如果此映射不包含key鍵的一射,則返回null。
     * <p>More formally, if this map contains a mapping from a key
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
     * key.equals(k))}, then this method returns {@code v}; otherwise
     * it returns {@code null}.  (There can be at most one such mapping.)
     * 更正式的說,如果此映射包含從鍵key到值value的映射,那麼執行(key==null ? k==null :
     * key.equals(k))操作,然後此方法返回返回值value,否則返回null。(最多可以有一個這樣的映射。)
     * <p>A return value of {@code null} does not <i>necessarily</i>
     * indicate that the map contains no mapping for the key; it's also
     * possible that the map explicitly maps the key to {@code null}.
     * The {@link #containsKey containsKey} operation may be used to
     * distinguish these two cases.
     * 返回null不代表地圖中不包含該key鍵的映射;有可能這個地圖中,將key鍵映射的值value爲null。containsKey操作可用於區分這兩種情況。
     *
     * @see #put(Object, Object)
     */

  從上面的註釋我們大概的瞭解到了,get()方法的作用查找哈希表中對應key鍵的value值,如果所對應的key鍵在map中有映射的value值,則返回value值,否則返回null。
  當get()方法返回爲null時,有一個特殊的情況,那就是key映射到map中的value值本身就爲空。在本方法中無法區分它們,但是在containsKey方法中可以區分它們。

2. 源碼剖析

	 public V get(Object key) {
        Node<K,V> e;
        // 在這裏執行getNode操作,要了解這裏的具體操作我們需要先看一下getNode方法,我們在下面分析一下這個方法。
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

getNode方法

	/**
     * Implements Map.get and related methods
     * 實現Map.get和相關方法
     * @param hash hash for key
     * @param key the key
     * @return the node, or null if none
     */
    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        // 哈希表已經初始化,且分的桶的頭節點不爲空
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            // 要查找結點的key值等於桶中頭節點的key值,直接返回頭節點
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            // 判斷桶中是否有其他結點,進行痛的遍歷
            if ((e = first.next) != null) {
            	// 若桶中元素已經樹化,使用樹的方式查找結點
                if (first instanceof TreeNode)
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                // 還未樹化,使用鏈表的方式(循環遍歷鏈表)進行查找結點
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        // 哈希表爲空,或桶爲空
        return null;
    }

  我們通過源碼分析可以發現,get()方法的核心是調用了getNode()方法,getNode()方法,返回了key鍵所在的結點,如果沒有則返回null,get()方法對該值進行判斷,然後取出value進行操作。

3. get()執行流程

  1. 若哈希表已經初始化並且桶的首結點不爲空
     ① 查找結點的key值恰好等於首結點的key值,直接返回首結點。
     ② 進行桶中元素的遍歷,查找指定結點
      a. 若樹化,按照樹的方法查找指定結點
      b. 按照鏈表方式查找
  2. 哈希表爲空或桶的首結點爲null,直接返回null。

4. containsKey(Object key)

	/**
     * Returns <tt>true</tt> if this map contains a mapping for the
     * specified key.
     * 如果此映射包含指定key鍵的映射,則返回true
     *
     * @param   key   The key whose presence in this map is to be tested
     * @return <tt>true</tt> if this map contains a mapping for the specified
     * key.
     */
    public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;
    }

  該方法也是調用了getNode方法,在這裏方法的作用時,判斷該key值在map中是否含有映射關係,如果含有映射關係,則返回true,狗則返回false。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章