publicfinal V setValue(V newValue){ V oldValue = value; value = newValue; return oldValue; }
// 复写equal方法 publicfinalbooleanequals(Object o){ if (o == this) returntrue; if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry<?,?>)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) returntrue; } returnfalse; } }
/** * The table, initialized on first use, and resized as * necessary. When allocated, length is always a power of two. * (We also tolerate length zero in some operations to allow * bootstrapping mechanics that are currently not needed.) */ // 存储元素的实体数组 transient Node<K,V>[] table;
/** * The number of key-value mappings contained in this map. */ // map的容量 transientint size;
/** * The next size value at which to resize (capacity * load factor). * * @serial */ // (The javadoc description is true upon serialization. // Additionally, if the table array has not been allocated, this // field holds the initial array capacity, or zero signifying // DEFAULT_INITIAL_CAPACITY.) // 当实际大小超过此值时,会进行扩容 threshold = 容量 * 加载因子 int threshold;
/** * The load factor for the hash table. * * @serial */ // 哈希表的加载因子,加载因子在这种实现方式中是数组被填充的程度,哈希表 // 填充的越满,发生冲突的机会越大。在Java的实现中默认的加载因子是0.75 finalfloat loadFactor;
接下来看一下HashMap默认的无参构造函数,看一下HashMap是如何初始化的:
1 2 3 4 5 6 7
/** * Constructs an empty <tt>HashMap</tt> with the default initial capacity * (16) and the default load factor (0.75). */ publicHashMap(){ this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted }
/** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. * * <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.) * * <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. * * @see #put(Object, Object) */ public V get(Object key){ Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; }
/** * Implements Map.get and related methods * * @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; // hash & (length - 1)得到红黑树的树根或者是链表头 if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { 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); } } returnnull; }