深入理解hashmap的原理

一、什么是哈希?

哈希也叫散列,是将不同长度的输入通过一个函数转换成同一个长度输出的过程,这个输出的值叫哈希值,这个转换函数叫哈希函数,哈希函数所采用的算法加哈希算法。(实际上是一个通过消息得到消息摘要的方法)

二、什么是哈希表?

哈希表是一个通过key存取value的数据结构,它是基于一个数组,存数据的时候,通过哈希函数f(key)得到一个值,这个值就是一个数组下标,然后将value存到数组对应下标的位置,取数据时则同样通过f(key)拿到位置取出值,由于数组通过下标存取数据的算法复杂度是 O(1),所以这个效率是非常高的。

三、什么是hashmap?

hashmap是以hash表为底层结构的存取键值对的数据结构,它同样基于一个数组,这个数组的每个元素是一个bucket,我们称之为桶。这个桶里面存放着一个链表,链表的元素是一个entry对象,entry中包含key,value,hash,next(链表的下个元素的位置),所以hashmap是数组和链表结合的数据结构。

存数据时,通过哈希函数f(key)得到数组的下标,然后将这个entry(键值对)存入到对应位置,取数据时,同样拿到下标从数组中取出entry,再从entry中拿到value。

四、什么是哈希冲突?

当往hashmap中存入数据时,hash函数通过key算出数组下标,虽然hash函数会尽量优化使得存的位置尽量均匀,但是仍然有可能这个下标已经存过其它数据,这时就产生了hash冲突,简单说就是两个数据存到一个位置,此时链表就有用了,新存入的数据会记录到链表的头,之前的数据往后移。

当这种情况取值时,我们首先找到这个位置的,然后遍历链表,通过key的equal方法找到与之相等的entry,然后从中取出value。

五、hashmap的负载因子是什么?

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

六、什么是hashCode()?为什么重写equal()方法也要同时重写hashCode()的方法?

hashCode()方法会调用一个本地方法 public native int hashCode(); 大概返回的是一个与对象内存地址相关的值,

正如我在hash里定义的,hashCode其实是返回的一个对象或数值的地址摘要信息,那么用他干什么呢?

我们往hashmap立put一个key-value的时候,哈希函数通过key得到一个数组下标,如果key是一个对象,那么这个哈希函数的输入

值的差异会非常大,转换也不方便,所以实际上我们hash的是key的hashCode,这样方便多了。

同样为什么重写equal()方法也要同时重写hashCode()呢,因为如果重写了equals方法,很可能是通过对象属性的值比较对象是否相等,

那么两个你以为相等的对象,比如两个人的对象person1,person2,你定义的是name、age、sex属性分别相等就对象相等,而实际是你把

person1与person2,put到hashmap的时候,他们的地址是不一样的,hashCode()也是不一样的,同样也会存入两个不同的下标中,取的时候

更不可能取到值。



猜你喜欢

转载自blog.csdn.net/shushucn2012/article/details/80308189