HashMap的构造函数大部分可以略过,挑了个进行分析
- public HashMap(Map<? extends K, ? extends V> m)
该构造函数,把已存在的Map添加至一个新的Map,该函数调用了putMapEntries(Map<? extends K, ? extends V> m, boolean evict)方法
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
if (table == null) { // pre-size
float ft = ((float)s / loadFactor) + 1.0F; // 根据加载因子获取长度
int t = ((ft < (float)MAXIMUM_CAPACITY) ? // 判断是否大于最大容量
(int)ft : MAXIMUM_CAPACITY); // 返回长度
if (t > threshold) // threshold默认为0
threshold = tableSizeFor(t); // 获取最近的2的整数次幂的数作为长度
}
else if (s > threshold) // 如果m的长度大于threshold
resize(); // 扩展map长度
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
putVal(hash(key), key, value, false, evict); // 把m的节点添加至该map
}
}
} - get()方法:
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value; // 判断是否存在相同的key,有则返回value,否则返回null
}
大致过程为:
对key的hashCode()做hash,然后再计算index
如果该 index 下没有值,则直接返回 null
index 下有值,判断 table 数组中该下标处第一个节点是否命中,命中则直接返回
未命中,则判断去树结构中查找,或者去链表结构中查找,找到则返回
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) { // 如果哈希表容量为0或者关键字没有命中,直接返回null
if (first.hash == hash && // always check first node // 第一个节点的hash是否和key的hash相等
((k = first.key) == key || (key != null && key.equals(k)))) // hash碰撞检测,如果hash相同,则调用equals进行判断
return first; // 如果链表第一个节点的key和hash都相等,表示存在相同的节点,则调用该节点
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)))) // key和hash都相等,表示存在相同的节点,则调用该节点
return e;
} while ((e = e.next) != null);
}
}
return null;
} - public boolean containsKey(Object key)
return getNode(hash(key), key) != null;
判断该map是否存在key节点 - put()方法:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
大致过程为:
对key的hashCode()做hash,然后再计算index
如果没碰撞直接放到bucket里
如果碰撞了,以链表的形式存在buckets里
如果碰撞导致链表过长(大于等于TREEIFY_THRESHOLD,默认为8),就把链表转换成红黑树
如果节点已经存在就替换old value(保证key的唯一性)
如果bucket满了(超过load factor * current capacity),就进行resize
2907

被折叠的 条评论
为什么被折叠?



