本章环境java1.8
hashmap的几个默认初始值
- DEFAULT_INITIAL_CAPACITY 数组默认大小 16
- DEFAULT_LOAD_FACTOR 负载因子默认0.75
- TREEIFY_THRESHOLD 默认8,链表超过8就转化成红黑树
- UNTREEIFY_THRESHOLD 默认6,链表数量少于6就会重新变成红黑树
- MIN_TREEIFY_CAPACITY 默认64,在编程红黑树之前,检查当前元素个数是否超过64,不超过不用转化红黑树
一些变量
- threshold 数组长度 * 负载因子
- size 记录当前存储的键值对的数量
- Node<K,V>[] table 记录
- loadFactor 负载因子
- modCount 记录修改次数
modCount
modCount是作为实现多线程并发操作的fail fast机制的一个标识符,用来标识当前对变量的修改次数,这里“修改”是指结构性修改,如何想深入了解,需要去到具体的类去看哪些操作对modCount进行了修改。对应modCount有一个expectedModCount,如果检测到expertedModCount和modCount不一致就会报ConcurrentModificationException错误。expertedModCount的初始化时在调用iterator()方法的时候设置的。
举个HashMap源码中keyset()的例子深入了解一下
public Set<K> keySet() {
Set<K> ks;
return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
}
//
final class KeySet extends AbstractSet<K> {
public final Iterator<K> iterator() { return new KeyIterator(); }
//
final class KeyIterator extends HashIterator
implements Iterator<K> {
public final K next() { return nextNode().key; }
}
//
abstract class HashIterator {
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
注意
HashMap<K,V> map = new HashMap<K,V>()时,不给table分配资源
public class Main5{
public static void main(String ...arg) throws Exception{
Class hashmap = Class.forName("java.util.HashMap");
Object map = hashmap.newInstance();
Field out = hashmap.getDeclaredField("loadFactor");
out.setAccessible(true);
System.out.println((float)out.get(map));
out = hashmap.getDeclaredField("threshold");
out.setAccessible(true);
System.out.println(out.get(map));
out = hashmap.getDeclaredField("size");
out.setAccessible(true);
System.out.println(out.get(map));
out = hashmap.getDeclaredField("table");
out.setAccessible(true);
Object[] a = (Object[])out.get(map);
System.out.println(a);
}
}