硬怼面试官系列:关于HashMap知道这五方面就够了1

本文详细探讨了HashMap的数据结构,包括数组+链表+红黑树的实现方式。接着阐述了hash函数的设计,如何通过异或运算减少碰撞。接着介绍了put过程,包括初始化、节点存储策略及何时转化为红黑树。还讨论了HashMap的扩容机制,当节点数量达到一定比例时,如何以2的倍数扩容。最后提到了线程安全问题,指出非同步的HashMap在多线程环境下的风险。
摘要由CSDN通过智能技术生成

一、HashMap的数据结构

HashMap<String,String> map=new HashMap();
map.put("1","Kobe");

这两行代码表示数据已经在HashMap中存储完成。而这也引发了一个问题,数据如何才能在HashMap中高效地存储?

从这个问题出发,我们首先应该了解HashMap的底层数据结构。

HashMap:数组+链表[单向链表]+红黑树 JDK1.8

 

我们都知道的是HashMap是存储键值对(key,value)的容器,那么从上图来看在每个小格子中应当放入key还是value或者都存放呢?

如果大家看过源码就会知道,这里采用了一种面向对象的思想,将【key,value】封装起来

class Node{
    private String key;
    private String value;
}

由此可知,每一个小格子就是一个new Node,而如果要将他们具体实现出来,只需要在Node的基础上稍加改动即可。

Node[] table=new Node[24];  //表示数组

class Node{
    private String key;     //表示单项链表
    private String value;
    Node next;
}

class TreeNode entends Node{     //红黑树的伪码表示
    parent;
    left;
    right;
}

二、hash函数和碰撞

当我们获取数据后,要将其存入到HashMap中,就需要确定key,value组成的Node对象在数组索引下标中的位置。

如果想要获取位置,就需要:

  • 数组长度 length
  • 得到一个整型数 [0 ---- length-1]

(1)我们首先可能想到用

Random.nextInt(length);

但是这样以来就会产生两个问题:

  1. 随机重复的可能性太大
  2. 查找时候没有依据

(2)鉴于这样的情况,hashCode就登场了:

  1. 得到整型数
int hash = key.hashCode()  ——> 32位的0和1组成的整数
如果我们用一个例子来表示:“1”.hashCode 有可能会超过存储范围

  1. 控制这个整型数的范围
这时就需要控制整形的hash值的范围:hash%length = 需要的范围

但即便是这样,也会产生一定的问题。在hash = key.hashCode();中,如果key的值是31,47之类的数,在模16后(hash%16)得到的结果都是1,这样Node对象去到同一个位置的可能性会比较大,存储的资源就会大大被浪费。

要使index的结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值