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。

猜你喜欢

转载自blog.csdn.net/meng_lemon/article/details/88953333
key
今日推荐