HashMap详解

源码:HashMap,Mybatis,Spring 建议看

 

HashMap: 数组+链表+(1.8之后红黑树)

 

Object类的hashCode:返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样

 

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

初始容量:1<<4 即 16.     

问 为什么初始容量 是16?

答:java的底层是c语言,C语言底层是汇编语言,汇编再往上就是机器语言,汇编编程使用的就是16进制,因此效率越高。

 

内部结构

有一个Node类

Node Implement Map.entry{
    hash
    key
    value
    next
}

Map.entry

interface Entry<K,V> {
    getKey()
    setKey()
    getValue()
    setValue()
    比较器,hash等抽象或具体实现的方法
}

当数据传进来时,首先会封装成Node,根据key取hash值,然后 hash(key) &(length()-1) ,存入数据

哈希冲突/碰撞:

1 单向链表:

    1.8之前 可以无限挂,1.8之后只能挂7个,第8个的时候转变为红黑树。最大容量为64,达到64再拆分。大于64会扩容。

    下挂节点<=6个,会将红黑树再转变为链表

问:为什么是6个时候转变?不是7个呢?

答:7个做准备,多一个是红黑树,少一个链表

/**
     * The bin count threshold for untreeifying a (split) bin during a
     * resize operation. Should be less than TREEIFY_THRESHOLD, and at
     * most 6 to mesh with shrinkage detection under removal.
     */
    static final int UNTREEIFY_THRESHOLD = 6;
/**
     * The smallest table capacity for which bins may be treeified.
     * (Otherwise the table is resized if too many nodes in a bin.)
     * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
     * between resizing and treeification thresholds.
     */
    static final int MIN_TREEIFY_CAPACITY = 64;

 

 

扩容因子0.75    

初始容量16,当存到12时,会扩容成32容量

问:hashMap的扩容怎么操作的?扩容后的元素如何均分的?

答:非常巧妙的处理:

0101 0101 0101 0101 0101 0101 0101 0101 = 每个Node的hash(key)值

0000 0000 0000 0000 0000 0000 0001 0000 = 32 容量

第五位若是0,则不变,若是1,则 当前位置 = 当前位置 +上一个容量 

/**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章