集合之HashMap 与 HashSet

1.你知道HashMap的get()方法的工作原理吗?

  • HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。
    当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。
    这里关键点在于指出,HashMap是在bucket中储存键对象和值对象,作为Map.Entry。

2.当两个对象的hashcode相同会发生什么?

  • 当hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。
  • 找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。
    总结:HashMap基于 hashing 原理。当put时,对key使用hashCode()方法,返回的hashCode 用于找到 bucket位置,存储Map.Entry 对象;bucket 存的是链表。get 时,先调用hashCode()来找到bucket,再调用重写的equals来找到对应的值。
  1. 如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?
  • 当一个map填满了75%的bucket时候,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。

4.你了解重新调整HashMap大小存在什么问题吗?

  • 当重新调整HashMap大小的时候,确实存在条件竞争,因为如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小。在调整大小的过程中,存储在链表中的元素的次序会反过来,因为移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。

所以HashMap是非线程安全的!

上一篇:KMP算法详解&&P3375 【模板】KMP字符串匹配题解


下一篇:10分钟开发一款“一键二次元化的”AI小程序