您的位置:首页 > 其它

HashMap工作原理

2018-01-21 21:40 190 查看
HashMap put() 和 get() 会用到 Object类的两个方法hashCode和equals

put()

首先put方法 存入key 和 value 时  会使用key.hashCode() 计算出 hash值得到 bucketindex 并将 key 和 value 存入 Entry(JDK1.8以下)或Node(JDK1.8)。

hash计算方法

hashCode&0x7FFFFFFF后,&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号外改变,而后面的位都不变。

如果相同key.hashCode()相同bucketindex也就相同,HashMap中重写equals比较了Entry(JDK1.8以下)或Node(JDK1.8)中key 是否相等。

如果相等value覆盖。

如果不等(HashMap使用哈希表来存储。哈希表为解决冲突,可以采用开放地址法和链地址法等来解决问题,Java 中 HashMap 采用了链地址法。)

对象hashCode发生碰撞时,HashMap通过链地址法解决,将新元素加入链表表头,通过next指向原有的元素。(JDK1.8以下)以此类推 (JDK1.8)以此类推8个 如果大小大于8,红黑树节点替换链表节点。

插入成功后,判断 table 数组大小是否超过了最大阈值,是的话扩容



阈值 = 容量 X 负载因子;容量默认为16,负载因子(loadFactor)默认是0.75 当元素个数大于12时就要扩容;那剩下的4个数组位置还没有放置对象就要扩容,就会浪费空间了。

loadFactor过大时,map内的数组使用率高了,内部极有可能形成Entry链,影响查找速度;

loadFactor过小时,map内的数组使用率旧低,不过内部不会生成Entry链,

或者生成的Entry链很短,由此提高了查找速度,不过会占用更多的内存;

所以可以根据实际硬件环境和程序的运行状态来调节loadFactor



默认 HashMap 默认初始容量为16,默认负载因子为0.75。也就是说put 第13次就会发生扩容,HashMap就需调用resize()方法重新分配table数组

resize()会将原来扩容2倍 map扩容后,要重新计算阈值;当元素个数大于新的阈值时,map再自动扩容; 

HashMap()构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空HashMap。

HashMap(int initialCapacity)构造一个带指定初始容量和默认加载因子 (0.75) 的空HashMap。

HashMap(int initialCapacity,float loadFactor)构造一个带指定初始容量和加载因子的空HashMap。

get(key) 

根据key.hashCode()和key取值

判断key.hashCode()在table中位置,

如果不是链表 根据key直接取值。

如果是链表 根据key 遍历所在下标处的Entry(链表结构),查找key 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HashMap