/** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. * * 返回指定键映射到的值,如果此映射不包含键的映射,则返回{@code null}。 * * <p>More formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such that {@code key.equals(k)}, * then this method returns {@code v}; otherwise it returns * {@code null}. (There can be at most one such mapping.) * * 更正式地说,如果这个映射包含一个键{@code k}到一个值{@code v}的映射, * 使得{@code key.equals(k)},那么这个方法返回{@code v};否则返回{@code null}。 * (最多可以有一个这样的映射。) * * @throws NullPointerException if the specified key is null 如果指定的键为空 */ public V get(Object key) { Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek; //扩展key的Hash值 inth= spread(key.hashCode()); //如果表格不为空且表格长度大于0且所查key的所在节点不为空,(n - 1) & h相当于取模操作,即获取其索引位置。 if ((tab = table) != null && (n = tab.length) > 0 && (e = tabAt(tab, (n - 1) & h)) != null) { //如果获取到当前值 if ((eh = e.hash) == h) { if ((ek = e.key) == key || (ek != null && key.equals(ek))) //返回当前节点值 return e.val; } //如果当前节点hash值小于0,溢出的时候为负数 elseif (eh < 0) //调用find方法,返回值,或者没找到则返回空 return (p = e.find(h, key)) != null ? p.val : null; //获取当前节点的下一个节点,如果非空,则判断是否相同,找到了即返回其值。 while ((e = e.next) != null) { if (e.hash == h && ((ek = e.key) == key || (ek != null && key.equals(ek)))) return e.val; } } returnnull; }
/** * Key-value entry. This class is never exported out as a * user-mutable Map.Entry (i.e., one supporting setValue; see * MapEntry below), but can be used for read-only traversals used * in bulk tasks. Subclasses of Node with a negative hash field * are special, and contain null keys and values (but are never * exported). Otherwise, keys and vals are never null. * 键值项。这个类永远不会作为用户可变的Map.Entry导出,但是可以用于批量任务中使用的只读遍历。 * 具有负哈希字段的Node的子类是特殊的,包含空键和值(但从不导出)。否则,键和val永远不会为空。 */ staticclassNode<K,V> implementsEntry<K,V> { //哈希码 finalint hash; //键 final K key; //值 volatile V val; //下一个节点 volatile Node<K,V> next;