/** * 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.) * * 哈希表,首次使用时初始化,并在必要时扩容。分配时长度总是2的幂。 * (某些操作允许长度为0,以支持目前不需要的引导机制。) */ transient Node<K,V>[] table;
/** * Holds cached entrySet(). Note that AbstractMap fields are used * for keySet() and values(). * * 缓存entrySet(),注意AbstractMap的字段用于keySet()和values()。 */ transient Set<Map.Entry<K,V>> entrySet;
/** * The number of key-value mappings contained in this map. * * 当前Map中键值对的数量。 */ transientint size;
/** * The number of times this HashMap has been structurally modified * Structural modifications are those that change the number of mappings in * the HashMap or otherwise modify its internal structure (e.g., * rehash). This field is used to make iterators on Collection-views of * the HashMap fail-fast. (See ConcurrentModificationException). * * HashMap结构性修改的次数。结构性修改指改变映射数量或内部结构(如rehash)。 * 该字段用于让Collection视图的迭代器快速失败(fail-fast)。 * (参见ConcurrentModificationException) */ transientint modCount;
/** * 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.) // (Javadoc描述在序列化时有效。如果table数组未分配,该字段保存初始容量,0表示DEFAULT_INITIAL_CAPACITY。) int threshold;
/** * The load factor for the hash table. * * 哈希表的负载因子。 * * @serial */ finalfloat loadFactor;
构造器
无参构造器
这个也是我们最常用的一个构造器,仅仅指定了负载因子,其他的字段都使用默认值。
1 2 3 4 5 6 7
/** * Constructs an empty {@code HashMap} with the default initial capacity * (16) and the default load factor (0.75). */ publicHashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted }
而负载因子是0.75,这个值在时间和空间的权衡之下的一个不错的选择。
1 2 3 4 5 6
/** * The load factor used when none specified in constructor. */ staticfinalfloatDEFAULT_LOAD_FACTOR=0.75f;
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * 将指定的值与此映射中的指定键关联。 * 如果该映射先前包含该键的映射,则旧值将被替换。 * * @param key key with which the specified value is to be associated * 要关联指定值的键 * @param value value to be associated with the specified key * 要与指定键关联的值 * @return the previous value associated with {@code key}, or * {@code null} if there was no mapping for {@code key}. * (A {@code null} return can also indicate that the map * previously associated {@code null} with {@code key}.) * 返回与key关联的前一个值,如果没有映射则返回null。 * (返回null也可能表示该映射之前将null与key关联。) */ public V put(K key, V value) { // 调用putVal方法,插入或更新键值对 return putVal(hash(key), key, value, false, true); }
/** * Computes key.hashCode() and spreads (XORs) higher bits of hash * to lower. Because the table uses power-of-two masking, sets of * hashes that vary only in bits above the current mask will * always collide. (Among known examples are sets of Float keys * holding consecutive whole numbers in small tables.) So we * apply a transform that spreads the impact of higher bits * downward. There is a tradeoff between speed, utility, and * quality of bit-spreading. Because many common sets of hashes * are already reasonably distributed (so don't benefit from * spreading), and because we use trees to handle large sets of * collisions in bins, we just XOR some shifted bits in the * cheapest possible way to reduce systematic lossage, as well as * to incorporate impact of the highest bits that would otherwise * never be used in index calculations because of table bounds. * * 计算key的hashCode,并将高位的hash通过异或运算混合到低位。 * 因为哈希表的长度总是2的幂,只有低位参与寻址,如果高位不同而低位相同会导致哈希冲突。 * 通过将高位与低位异或,可以让高位的信息参与寻址,减少哈希冲突。 */ staticfinalinthash(Object key) { int h; // 如果key为null,返回0,否则返回hashCode与其高16位右移后异或的结果 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
/** * 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) * * 返回指定key对应的value,如果没有该key的映射则返回null。 * 注意,返回null不一定表示没有该key的映射,也可能是该key被显式映射为null。 * 可以通过containsKey方法区分这两种情况。 */ public V get(Object key) { Node<K,V> e; return (e = getNode(key)) == null ? null : e.value; }