HashMap面试题

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

  “HashMap 是基于 hashing 的原理,我们使用 put (key, value)存储对象到 HashMap 中,使用 get (key)从 HashMap 中获取对象。当我们给 put ()方法传递键和值时,我们先对键调用 hashCode ()方法,返回的 hashCode 用于找到 bucket 位置来储存 Entry 对象。”这里关键点在于指出,HashMap 是在 bucket 中储存键对象和值对象,作为 Map.Entry。这一点有助于理解获取对象的逻辑。如果你没有意识到这一点,或者错误的认为仅仅只在 bucket 中存储值的话,你将不会回答如何从 HashMap 中获取对象的逻辑。这个答案相当的正确,也显示出面试者确实知道 hashing 以及 HashMap 的工作原理。但是这仅仅是故事的开始,当面试官加入一些 Java 程序员每天要碰到的实际场景的时候,错误的答案频现。

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

    从这里开始,真正的困惑开始了,一些面试者会回答因为 hashcode 相同,所以两个对象是相等的,HashMap 将会抛出异常,或者不会存储它们。然后面试官可能会提醒他们有 equals ()和 hashCode ()两个方法,并告诉他们两个对象就算 hashcode 相同,但是它们可能并不相等。一些面试者可能就此放弃,而另外一些还能继续挺进,他们回答“因为 hashcode 相同,所以它们的 bucket 位置相同,‘碰撞’会发生。因为 HashMap 使用 LinkedList 存储对象,这个 Entry (包含有键值对的 Map.Entry 对象)会存储在 LinkedList 中。”这个答案非常的合理,虽然有很多种处理碰撞的方法,这种方法是最简单的,也正是 HashMap 的处理方法。

3.“如果两个键的 hashcode 相同,你如何获取值对象?” 

    面试者会回答:当我们调用 get ()方法,HashMap 会使用键对象的 hashcode 找到 bucket 位置,然后获取值对象。面试官提醒他如果有两个值对象储存在同一个 bucket,他给出答案:将会遍历 LinkedList 直到找到值对象。面试官会问因为你并没有值对象去比较,你是如何确定确定找到值对象的?除非面试者直到 HashMap 在 LinkedList 中存储的是键值对,否则他们不可能回答出这一题。

  其中一些记得这个重要知识点的面试者会说,找到 bucket 位置之后,会调用 keys.equals ()方法去找到 LinkedList 中正确的节点,最终找到要找的值对象。完美的答案!

  许多情况下,面试者会在这个环节中出错,因为他们混淆了 hashCode ()和 equals ()方法。因为在此之前 hashCode ()屡屡出现,而 equals ()方法仅仅在获取值对象的时候才出现。一些优秀的开发者会指出使用不可变的、声明作 final 的对象,并且采用合适的 equals ()和 hashCode ()方法的话,将会减少碰撞的发生,提高效率。不可变性使得能够缓存不同键的 hashcode,这将提高整个获取对象的速度,使用 String,Interger 这样的 wrapper 类作为键是非常好的选择。

4.   “如果 HashMap 的大小超过了负载因子(load factor)定义的容量,怎么办?”

    除非你真正知道 HashMap 的工作原理,否则你将回答不出这道题。默认的负载因子大小为 0.75,也就是说,当一个 map 填满了 75% 的 bucket 时候,和其它集合类(如 ArrayList 等)一样,将会创建原来 HashMap 大小的两倍的 bucket 数组,来重新调整 map 的大小,并将原来的对象放入新的 bucket 数组中。这个过程叫作 rehashing,因为它调用 hash 方法找到新的 bucket 位置。

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

    你可能回答不上来,这时面试官会提醒你当多线程的情况下,可能产生条件竞争(race condition)。

  当重新调整 HashMap 大小的时候,确实存在条件竞争,因为如果两个线程都发现 HashMap 需要重新调整大小了,它们会同时试着调整大小。在调整大小的过程中,存储在 LinkedList 中的元素的次序会反过来,因为移动到新的 bucket 位置的时候,HashMap 并不会将元素放在 LinkedList 的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。这个时候,你可以质问面试官,为什么这么奇怪,要在多线程的环境下使用 HashMap 呢?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值