HashMap底层分析

1、主要参数

桶容量(Capacity)默认16

极限容量为2的30次方

加载因子为0.75f

阈值,当map中entry数量大于此阈值时进行扩容,数组大小*加载因子

2、数据结构

JDK1.7及以前是用数组+单链表 Entry<K,V>[] table

Entry内部类如下:

static class Entry<K,V> implements Map.Entry<K,V> {

    final K key;

    V value;

    Entry<K,V> next;

    int hash;

}

 

JDK1.8中,HashMap采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间

允许null值与null键

 

3、计算规则

hash算法是计算key值得到哈希桶的下标值即索引值。

目的使元素分布均匀,提高查询效率。

JDK1.8: return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

JDK1.7: return h & (length-1);

4、碰撞

如何避免:使用好的hash算法,扩容机制

具体描述:hashMap的数据结构,hash算法实现过程,扩容机制使用场景

5、扩容

HashMap实际容量是2的n次方,当元素个数大于扩容阈值,扩容到原来的两倍,并重新计算存储位置

JDK1.8: 扩容位置 = 原位置 or 原位置+旧容量

JDK1.7: 按照原来计算方法进行 h & (length-1)

6、HashMap查询

分四步: 

  1. 判断key,根据key算出索引。 
  2. 根据索引获得索引位置所对应的键值对链表。 
  3. 遍历键值对链表,根据key找到对应的Entry键值对。 
  4. 拿到value

7、HashMap增加元素

  1. 接收需存储的键值对
  2. 根据key值计算索引值
  3. 根据计算的hash值找到数组下标
  4. 判断是否产生冲突,否存入到相应数组位置
  5. 冲突的话判断是否红黑树还是单链表
  6. 红黑树结构尾插法插入或者覆盖,链表长度>8使用红黑树结构,<8使用单链表结构

8.HashMap的长度为什么是2的倍数

在HashMap的操作流程中,首先会对key进行hash算法得到一个索引值,这个索引值就是对应哈希桶数组的索引。为了得到这个索引值必须对扰动后的数跟数组长度进行取余运算。即 hash % n (n为hashmap的长度),又因为&比%运算快。n如果为2的倍数,就可以将%转换为&,结果就是 hash & (n-1)。所以这就解释了为什么HashMap长度是2的倍数。也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方,尽量较少碰撞,也就是要尽量把数据分配均匀

9、工作原理

基于hashing原理,通过put()和get()方法存储和获取对象。使用put()方法时候,通过键值对使用方法hashCode()计算hashCode,然后找到对应的索引位置存放数据;使用get()方法时候,通过equals()方法找到正确的键值,然后返回对象,如果发生碰撞,调用循环遍历list,通过keys.equals()找到正确的点

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值