笔记总结-Java集合

本文详细介绍了Java HashMap的工作原理,包括容量必须为2的幂、扩容边界值、put方法的实现、哈希值计算、扩容与树化的时机,以及解决哈希冲突的策略。对比了JDK1.7与1.8的区别,讨论了为何不直接使用红黑树以及加载因子设为0.75的原因。同时,提到了ConcurrentHashMap与HashMap的异同,强调了HashMap的线程不安全性。
摘要由CSDN通过智能技术生成

1、hashmap的数组容量一定是2的几次幂

  1. 在new Hahmap()的时候如果不传递参数,默认的初始化容量就是16
  2. 如果传递参数,比如传递28,那initcapacity就是28,会走这段代码:(每次左移1位,都乘以2,说明就是2的n次幂)
    int capacity=1;
    while(capacity<initCapacity)
    capacity<<=1;

2、hashmap扩容的边界值是12

  1. Math.min(capacity装载因子,数组的最大容量+1)求最小值的结果就是160.75=12
  2. 当数组>12时,数组扩容

3、hashmap存储数据的put方法

  1. 通过key值获取哈希码h^=k.hascode
  2. 根据哈希拿到元素在数组的位置h&(table.length-1)相当于h%length
  3. 添加元素的方法addEntry(当未到达阈值会createEntry,到达阈值会将数组扩容成原来的2倍)
  4. 当出现哈希碰撞时,7上8下(jdk1.7插入到当前元素之前,当jdk1.8之后会插入到当前元素的后面)(多线程同时操作及逆行扩容时,可能会有循环链表的出现)
  5. 当出现哈希碰撞时,先比较哈希hash再比较equals(key)值

4、hashmap中计算key的哈希值

jdk1.7

  1. 通过key获得哈希码的时候,没有直接hascode拿到哈希值
  2. 而是通过二次散列(通过一个异或的运算h^=k.hascode)
  3. 核心思想是增加哈希码的不确定性,不会轻易的出现哈希碰撞
    h=(h>>>20)(h>>12)等等

jdk1.8时:
4. h=key.hascode()^(h>>>16)也是为了让高16位和低16位同时参与运算,让数据散列更加均匀

5、 扩容的时机

  1. 第一次put时,数组的长度为null,也会resize扩容
  2. 数组的长度大于容量*加载因子

  1. 扩容的大小是左移一位,原来的2倍

6、树化的时机

  1. 容量大于等于64(当数组的容量没有达到64,会优先选择扩容而不是树化)
  2. 链表的长度大于等于8

  1. 为什么大于8的时候会树化?

7、解决哈希冲突的几种办法:

  1. 再散列法:通过H(key)拿到哈希值出现哈希碰撞后,以这次的H(key)为基础,再次hash,依次类推,直到不出现哈希碰撞为止,再哈希法的哈希表的长度要远远大于需要存放的元素,因为要再哈希,又不能把之前的H(key)删掉,只能做删除标记,不能真正删除结点
  2. 再哈希法:提供了多种hash方法,第一种hash不行,换第二种࿰
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值