HashMap的工作原理

来源:互联网 发布:fate hf 知乎 编辑:程序博客网 时间:2024/06/10 08:51

首先,先回答一些简单的问题:“你用过HashMap吗?” “什么是HashMap?你为什么用它”

几乎每个人都会回答“是的”,然后阐述一些HashMap的特性,如HashMap可以接受null键值和值,而Hastable不行;

HashMap是非synchronized,而HashTable是synchronized,这意味着HashTable是线程安全的,多个线程可以共享一个HashTable;以及HashMap是存储键值对的形式等。

那么,接着回答“你知道HashMap的工作原理吗?”尴尬我不知道啊。。。。。。

所以,我查了查,就记录下来。


1.HashMap的工作原理:

HashMap基于Hashing原理,我们通过put()和get()方法存储和获取对象。当我们的将键值对传递给put()方法时,它调用HashCode()方法来计算hashcode,然后找到bucket位置来存储值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回对象。


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

因为Hashcode相同,所以它们的bucket位置相同,会发生“碰撞”。因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。


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

(1)首先,你会说:当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,然后获取值对象。

  这时,面试官会提醒如果有两个值对象存储在同一个bucket......

(2)这时,你停顿三秒,灵光一闪偷笑说:遍历链表直到找到值对象。

  但是,问题又来了,你没有值对象去比较,你是如何确定找到值对象的?或许这里已经有很多人晕了。。。。。

(3)找到bucket位置后,会调用keys.equals()方法去找链表中正确的节点,最终找到值对象,perfect!

 这里还有一点,可以使用不可变的、声明作fianl的对象,并且采用合适的equals()方法和hashcode()方法,将会减少碰撞的发生,提高效率。我就不太理解,往大神赐教!


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

默认的负载因子大小为0.75,也就是说,当一个map填满75%的bucket时候,和其他集合类一样,将会创建原来HashMap大小两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调整hash方法找到新的bucket位置。


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

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


6.为什么String、Integer这样的包装类适合作为键?

因为String是不可变的,也是final的,而且已经重写了equals()和hashcode()方法了。不可变性是必要的,因为要计算hashcode(),就要防止键值的改变,如果键值在放入时和获取时返回的不同的hashcode的话,那么就不能从HashMap中找到你想要的对象。不可变性还具有其他的优点如线程安全,因为获取对象时要用到hashcode()和equals()方法,所以键对象正确的重写这两个方法是非常重要的。如果两个不相等的对象返回不同的hashcode()的话,那么碰撞的几率就会减小,这样可以提高HashMap的性能。


7.我们可以使用自定义的对象来作为键吗?

你可以使用任何对象作为键,只要它遵循了equals()和hashcode()方法的定义规则,并且当对象插入到Map中之后将不会再改变了。如果这个自定义对象时不可变的,那么它已经满足了作为键的条件,因为当它创建之后就不能改变了。


8.我们可以使用CurrentHashMap来代替Hashtable吗?

我们知道,Hastable是synchronized的,但是CurrentHashMap的同步性更好,因为它仅仅根据同步级别对map的一部分进行上锁。CurrentHashMap可以代替Hashtable,但是Hashtable提供更强的线程安全性。


先总结这么多,部分内容还有待更加深入的探讨,大家有什么不同的观点,欢迎留言,共同学习!




0 0
原创粉丝点击