HashMap总结

本文详细解析了Java8中HashMap的内部实现,包括其参数设置、数据结构变化、hash值获取方式、put操作流程、链表插入改进以及hash碰撞解决策略。特别关注了与Java7的不同之处,如链表转红黑树的条件与目的。
摘要由CSDN通过智能技术生成

HashMap是写程序经常使用到的类。
而hashmap也是面试时候经常问到的考点,下面结合源码总结一些hashmap的问题,本文以java8作为参考,也会讲与jdk1.7的部分区别:

1、hashmap的几个参数

默认初始化容量大小:DEFAULT_INITIAL_CAPACITY = 16;
最大桶容量:MAXIMUM_CAPACITY = 1073741824;
默认加载因子:DEFAULT_LOAD_FACTOR = 0.75f;
链表转红黑树的链表长度:TREEIFY_THRESHOLD = 8
链表转红黑树,桶最小容量:MIN_TREEIFY_CAPACITY = 64
红黑树转链表,红黑树的大小:UNTREEIFY_THRESHOLD = 6;

2、hashmap的数据结构是什么样子的
jdk1.7的数据结构为:数组+链表
jdk1.8及以后的数据结构为:数组+链表+红黑树

3、hashmap中hash值是如何获取的

static final int hash(Object paramObject)
  {
    int i;
    return paramObject == null ? 0 : (i = paramObject.hashCode()) ^ i >>> 16;
  }

将hashcode与它本身左移16位做了异或。目的是为了更好的散列

4、HashMap如何put进数据

putVal代码如下:

 final V putVal(int paramInt, K paramK, V paramV, boolean paramBoolean1, boolean paramBoolean2)
  {
    Node[] arrayOfNode;
    int i;
    //若为空则先初始化
    if (((arrayOfNode = this.table) == null) || ((i = arrayOfNode.length) == 0)) {
      i = (arrayOfNode = resize()).length;
    }
    int j;
    Object localObject1;
    //此处寻址桶处无值,则进行数据插入
    if ((localObject1 = arrayOfNode[(j = i - 1 & paramInt) ]) == null)
    {
      arrayOfNode[j] = newNode(paramInt, paramK, paramV, null);
    }
    else
    {
     //其他情况数据插入,分别分为treenode和链表两种情况
      ....
      }
    this.modCount += 1;
    //如果达到扩容条件,则扩容,桶数量*扩容因子
    if (++this.size > this.threshold) {
      resize();
    }
    afterNodeInsertion(paramBoolean2);
    return null;
  }

方法里面寻桶算法如下:

if ((localObject1 = arrayOfNode[(j = i - 1 & paramInt)]) == null)
  {
    arrayOfNode[j] = newNode(paramInt, paramK, paramV, null);
  }

如果是使用new HashMap();新建一个hashmap对象,初始容量为16,扩容因子0.75,当put进去的值满足如下条件:1、桶的大小大于64 2、插入的桶对应链表长度大于8,则将把链表转为红黑树。这种条件是比较苛刻的,源码里面有注释说明,在理想状态下,满足能将链表转为红黑树的概率:less than 1 in 10 millions

5、关于链表插入方面
HashMap在jdk1.8的时候,链表插入值从1.7的前插变成了尾插,原因是因为1.7使用前插的方式,在多线程高并发环境,可能造成死循环。当然,一般来说,碰到多线程的情况,使用concurrentHashMap更为合理

6、hashmap如何解决hash碰撞的问题
hash碰撞,对于桶数确定的数据结构,是一定会碰到的问题。首先,hashmap本身对于hashcode有重写,并且对寻桶算法上面,使用的也不是传统的取模运算,而是用的&运算,就是为了尽可能的散列,减少碰撞。一旦发生碰撞,一般的解决方案有两种:1、在碰撞的地方往后寻找位置进行放值,2、使用链表。hashmap使用链表的方式解决hash碰撞的问题,即一旦发生碰撞,则将值放入该桶对应的链表上面去

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值