HashMap:
hashmap的一些参数默认初始值:
DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 默认初始容量:16
MAXIMUM_CAPACITY = 1 << 30; 默认最大容量:10亿多
DEFAULT_LOAD_FACTOR = 0.75f; 默认负载因子:0.75 ???有什么用?
TREEIFY_THRESHOLD = 8; 默认阈值阈值:8
UNTREEIFY_THRESHOLD = 6; 默认取消阈值:6
MIN_TREEIFY_CAPACITY = 64; 默认最小存储容量:64
/**
* The next size value at which to resize (capacity * load factor).当前阈(yù)值(达到该值,则进行扩容)
*
* @serial
*/
int threshold;
阈值:12 24 48 96
总的容量:16 32 64 128
int modCount; 记录map修改次数
数组:
/**
* 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;
结构体(链表):
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
(二叉树):
/** * Entry for Tree bins. Extends LinkedHashMap.Entry (which in turn * extends Node) so can be used as extension of either regular or * linked node. */ static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { TreeNode<K,V> parent; // red-black tree links TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev; // needed to unlink next upon deletion boolean red;
put方法:
首先计算key的hash值:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
^:异或,相同为0,不同为1;
if (++size > threshold)//判断,当前长度+1 与 容量*偏移量的值的大小
resize();//
afterNodeInsertion(evict);//将值保存在hashmapentryset类属性中。
遍历录入 <KEY,VALUE>
/**
* Holds cached entrySet(). Note that AbstractMap fields are used
* for keySet() and values().
*/
transient Set<Map.Entry<K,V>> entrySet;
可以放 <null,null>
判断是否需要扩张成红黑树 操作
binCount:数组后跟的链表大小
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash);// 桶装不下,则查看是否需要扩张成红黑树 break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } }
/** * Replaces all linked nodes in bin at index for given hash unless * table is too small, in which case resizes instead. 当桶的大小超过8,且hash表数组长度大于等于 64 ===》链表转二叉树 */ final void treeifyBin(Node<K,V>[] tab, int hash) {
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY) resize(); else if ((e = tab[index = (n - 1) & hash]) != null) {
remove:
/**
* Implements Map.remove and related methods.
*
* @param hash hash for key
* @param key the key
* @param value the value to match if matchValue, else ignored
* @param matchValue if true only remove if value is equal
* @param movable if false do not move other nodes while removing
* @return the node, or null if none
*/
final Node<K,V> removeNode(int hash, Object key, Object value,
boolean matchValue, boolean movable)
(p = tab[index = (n - 1) & hash]) != null) {//怎么算出key所在位置???
/** * Replaces all linked nodes in bin at index for given hash unless * table is too small, in which case resizes instead. 当桶的大小超过8,且当前hash表数组长度大于等于 64 ===》链表转二叉树 */ final void treeifyBin(Node<K,V>[] tab, int hash)
LinkedHashMap:
class LinkedHashMap<K,V>
extends HashMap<K,V>
所以 很多方法都是使用的 HashMap的方法。
```java
/**
* HashMap.Node subclass for normal LinkedHashMap entries.
* 双向双链表结构
*/
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
```
线程不安全