HashMap & ConcurrentHashMap

1. HashMap索引位置的计算

1.1 hashCode, hash, index之间的关系

  • put/get一个元素的时候,会调用该元素的hashCode方法,比如下面的自定义KeyObject类
    KeyObject

  • hashCode的数据会被用来计算hash值
    hash
    如果细心的小伙伴,去print一下这个hash值,就会发现其实是一个非常大的整数,比如2028737这样的,显然这个hash值不会是底层Entry[]数组的index值

    1.2 index的计算原则

    Entry[]数组的长度在初始化的时候会被指定,假定这个值为length。
    那index的值就从 0 ~ length-1。所以index需要尽可能的平衡,也就是分布均匀,不能某些位置上存储特别多的数据,某些位置上又特别少。
    前面我们说过,通过hash值来计算index,那使用什么办法可以满足:性能高效、均匀分析
    官方的做法是 index = hash值 & (length -1)

    2. 为什么重写Equals方法时必须要重写HashCode方法?

    首先,是为了提高效率,采取重写hashcode方法,先进行hashcode比较,如果不同,那么就没必要在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大的效率提高是很明显的,一个很好的例子就是在集合中的使用。
    我们都知道java中的List集合是有序的,因此是可以重复的,而set集合是无序的,因此是不能重复的,那么怎么能保证不能被放入重复的元素呢,但靠equals方法一样比较的话,如果原来集合中以后又10000个元素了,那么放入10001个元素,难道要将前面的所有元素都进行比较,看看是否有重复,欧码噶的,这个效率可想而知,因此hashcode就应遇而生了,java就采用了hash表,利用哈希算法(也叫散列算法),就是将对象数据根据该对象的特征使用特定的算法将其定义到一个地址上,那么在后面定义进来的数据只要看对应的hashcode地址上是否有值,那么就用equals比较,如果没有则直接插入,只要就大大减少了equals的使用次数,执行效率就大大提高了。同时也是为了保证同一个对象,保证在equals相同的情况下hashcode值必定相同,equals不同的情况下hashCode必定不同。如果重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的(因为equal都是根据对象的特征进行重写的),但hashcode确实不相同的。这样的话,你调用containsKey(Object key)方法时,由于我们是通过key 的hashCode值,经过hash运算后,再得到index 的,明明在HashMap中已经有与key equals相等的元素了,但是由于我们没有重写hashCode方法,他们的hashcode值不同,索引containsKey返回的将会是false,不是我们想得到的true。

    总结来说就是两点

    1.使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率

    2.保证是同一个对象,如果重写了equals方法,而没有重写hashcode方***出现equals相等的对象,hashcode不相等的情况,重写hashcode方法就是为了避免这种情况的出现。

全部评论

相关推荐

10-07 23:57
已编辑
电子科技大学 Java
八街九陌:博士?客户端?开发?啊?
点赞 评论 收藏
分享
牛客339922477号:都不用reverse,直接-1。一行。啥送分题
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务