HashMap:
HashMap----数据结构:
// 初始容量
static final int DEFALUT_INITIAL_CAPACITY = 1 << 4 ;
// 最大容量
static final int MAXINUM_CAPACITY = 1 << 30 ;
// 扩容因子
static final float DEFAULT_LOAD_FACTOR = 0.75;
// 当添加一个元素被添加到有至少TREEIFY_THRESHOLD 个节点的桶中,桶中链表将被转化为树形结构
final int TREEIFY_THRESHOLD = 8
// 树转链表
final int UNTREEIFY_THRESHOLD = 6;
// 数组长度 > 64 && 链表节点 > 8 ,链表才能转红黑树
static final int MIN_TREEIFY_CAPACITY = 64;
HashMap----构造函数:
// 1
public HashMap(){
this.loadFactor = DEAULT_LODD_FACTOR;
}
// 2
public HashMap(int initalCapacity){
this(initCapacity , DEFAULT_LOAD_FACTOR);
}
// 3
public HashMap(Map < ? extends k, ? extends V> m){
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m,false);
}
// 4
public HashMap(int initialCapacity, float loadFactor) {
// capacity < 0 抛出异常
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
// capacity > 最大的capacity 直接,将最大的capacity赋值给 initCapacity
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
// 加载因子必须要 大于等于 0 && 必须是float 否则抛出异常
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
// tableSizeOf 用于位运算(取模)来确定数组大小
this.threshold = tableSizeFor(initialCapacity);
}
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
HashMap----put:
// put
public V put(K key,V value){
return putVal(hash(key),key,value,false,true);
}
// putVal onlyIfAbsent == false不改变现有值, evict == true 创建状态
final V putVal(int hash,K key,V value,boolean onlyIfAbsent,boolean evict){
Node<K,V>[] tab;
Node<K,V> p;
int n,j;
// 当散列表为null时,调用resize()初始化散列表
if((tab = table) == null || (n = table.length) == 0){
n = (tab.resize()).length;
}
}
// hash
static final int hash(Object key){
int h;
return (key == null) ? 0: (h = hashcode(key) ^ (h >>> 16));
}
// putMapEnties
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 = tableSizeFor(t);
} else {
// Because of linked-list bucket constraints, we cannot
// expand all at once, but can reduce total resize
// effort by repeated doubling now vs later
while (s > threshold && table.length < MAXIMUM_CAPACITY)
resize();
}
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);
}
}
}