面试题-容器2-hashMap原理

19 篇文章 0 订阅
2 篇文章 0 订阅
1、HashMap的工作原理
1.1、put
  • 当使用put(key, value)存储对象到HashMap中时,会首先对键调用hashCode()方法,计算并返回hashCode是用于找到Map数组的bucket位置来存储Node对象。
  • 如果Hash值对应的数组元素没有发生碰撞(无值),则直接放入当前位置中;若发生了碰撞,则以链表的方式链接到后面。
  • 若链表长度超过阈值(一般为8),则将链表转化为红黑树,链表长度若低于一定值(6),就把红黑树转化为链表。
  • 若链表或红黑树中已经存在,则替代它。
  • 若桶满了(容量16*加载因子0.75),就需要resize(扩容2倍后重新排列)。
1.2、get
  • 当我们调用get()方法时,HashMap会通过键对象hashcode找到对应的数组位置,找到之后通过keys.equals()方法找到链表中正确的节点,最终找到正确的对象。
1.3、减少碰撞的方法?
  • 为什么String适合做为键:因为String是final的,而且重写了equals()和hashCode()方法。如果要计算hashCode就要防止键值改变,如果键值在放入时和获取时返回不同的hashCode的话,就不能哦才能够HashMap中找到想要的对象。
1.4、hash过程?
  • hash公式:hashCode(key) & (Length - 1);
1.5、为什么使用红黑树?为什么不一直使用红黑树?
  • 二叉树在特殊情况下会变成一条线性结构,遍历跟之前一样。红黑树在插入新数据之后回经过左旋、右旋、变色这些操作来保持平衡。
  • 红黑树属于平衡二叉树,如果链表端的话,会损耗性能;链表长的时候,红黑树效率更高。
1.6、红黑树的理解?

见3。

1.7、若HashMap大小超过了负载因子定义的容量怎么办?
  • 当一个Map填满了75%的bucket时,会将原来HashMao大小的两倍的bucket数组来调整Map的大小,将原来的对象放入新的bucket数组中。
  • 这个值可能在两个地方,一个是原下标的位置,另一个实在下标为<原下标+原容量>的位置。
1.8、重新调整的HashMap存在什么问题?
  • 重新调整HashMap大小的时候,存在条件竞争。
  • 如果两个线程同时发现了HashMap需要调整大小,会同时试着调整大小。在调整大小的过程中,链表会首位互换,这是为了避免尾部遍历,若竞争发生,就是死循环。
1.9、HashMap的扩容?
  • 认识两个变量Capacity:HashMap的当前长度,是2的幂;LoadFactor:HashMap的负载因子,默认值为0.75f。衡量是否需要进行Resize的条件是:HashMap.Size >= Capacity * LoadFactor。
  • Resize的步骤:
    1)、扩容:创建一个新的Entry空数组,长度是原数组的2倍。
    2)、ReHash:遍历原Entry数组,把所有的Entry重新Hash到新的数组。
  • 可能会出现死链:两个线程导致链表出现环形,导致了死循环。
2、ConcurrentHashMap
2.1、可以使用ConcurrentHashMap代替HashTable么?
  • ConcurrentHashMap的同步性能比HashTable更好,因为仅仅根据同步级别对map的一部分上锁;
  • ConcurrentHashMap可以代替HashTable,但是HashTable可以提供更强的线程安全;
  • 他们都可以用到多线程环境。当HashTable的大小增大到一定量的时候,性能会下降,因为迭代需要锁定的时间会很长。ConcurrentHashMap引入了分割,无论Map变得多大,仅需要锁定Map的某个部分,其他线程不需要等到迭代完成才能访问Map。ConcurrentHashMap会锁定Map的某个部分,HashTable会锁定整个Map。
2.2、ConcurrentHashMap运行原理
  • 采用了CAS+synchronized来保证并发安全性。
2.2.1、CAS
  • CAS有三个操作数:V内存值、A旧的预期值、B要修改的新值。当且仅当A和V相同时,将内存值V修改为B,否则什么都不做。
  • CAS会出现的问题:ABA;
    解决方案:对变量增加一个版本号,每次修改版本号加1,比较的时候比较版本号。
2.2.2、put过程
  • 根据key计算出hashcode;
  • 判断是否需要进行初始化(即Map为空),若需要,则初始化;
  • 判断该节点上是否存在数据,若不存在,则直接赋值;若存在,则若该节点的hash值为MOVED(-1),则对该桶中的节点进行转移;
  • 若hash值不是-1,则对bucket中的第一个节点(即数组元素)进行加锁(synchronized),对该bucket进行遍历,bucket中的hash值与key和给定的hash值与key相等,则替换value值;若没找到相等的,则直接新生成一个结点并赋值为最后一个节点的下一个节点;
  • 若bitCount值达到红黑树转化的阈值,则将bucket中的结构转化为红黑树。
3、红黑树
3.1、简介
  • 每个节点是红色或者黑色;
    根节点是黑色;
    每个叶子节点是黑色(指为空的叶子节点);
    若一个节点是红色,则他的子节点必须是黑色;
    从一个节点到该节点的子孙节点所有路径上包含相同数目的黑节点;
    新插入节点为红色节点;
    任意节点左右子树最多相差两层红色节点;

  • 时间复杂度为O(logn)

  • 左旋、右旋

  • 添加的步骤:将红黑树当作一棵二叉查找树,将节点插入;将插入节点着色为“红色”(为了上述第五点);通过旋转和着色操作,使其成为一棵红黑树。

  • 红黑树性能要比平衡二叉树高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值