HashMap

1、数据结构

    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    static final int MAXIMUM_CAPACITY = 1 << 30;
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    static final int TREEIFY_THRESHOLD = 8;
    static final int UNTREEIFY_THRESHOLD = 6;
    static final int MIN_TREEIFY_CAPACITY = 64;

    transient Node[] table;
    transient int size;
    transient int modCount;
    int threshold;
    final float loadFactor;


    static class Node implements Map.Entry {
        final int hash;
        final K key;
        V value;
        Node next;

    }

 

2、核心方法

(1)初始化,初始化指定默认大小=16,加载因子=0.75,如果指定了初始化容量,根据位或运算,最终会成为2的整数幂

public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        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;
 }

(2)put

3、问题qa

(1)为什么默认的扩展因子是0.75

(2)1.7版本的死循环、1.8版本的死循环

1.7版本 链表头部插入,扩容成为新的链表时,仍然时头部插入,

链表 a,b,c,
线程1完成扩容,c,b,a
线程2,扩容时,显示 a--->null,然后 b-->a-->null,最后 b.next时已经发生变化,又重新指向了a,此时链表是a-->b-->a, 

(3)为什么线程不安全

4、备注
(1)jdk1.8之前是插入链表头部,1.8之后是插入链表尾部

(2)jdk1.8优化,当链表个数>7时,使用红黑树进行管理

你可能感兴趣的:(java)