• Java基础之HashCode解读


    前言

    在Object类中,提供了一个native方法,public native int hashCode(),该方法的返回值类型是int类型。

    Hash的概念 

    Hash,一般翻译成“散列”,或者直译为“哈希”,把任意长度的输入x,通过散列算法f(x),变成固定的长度输出,该输出值就是散列码。

    1.如果结构中存在和输入值K相等的记录,则必定在f(K)的存储位置上。

    2.对应关系f称为散列函数,按这个事先建立的表称为散列表,散列表由多个bucket构成,每个bucket可以存储多个散列码的位置。

    3.对于两个不同的输入值K1、K2,可能得到的散列码不同,即,K1 != K2  → f(K1) == f(K2) ,这种现象称为碰撞。

    4.在同一个散列函数中,如果两个输入值K1、K2,得到的散列码 f(K1) != f(K2),那么K1与K2必定不相同。

    HashCode的概念

    HashCode是JDK根据对象的地址,或者字符串或者数字算出来int类型的值,这个值我们称为HashCode,换一句话来说,上述提到通过散列函数得出的散列码就是HashCode。

    HashCode的几个重要的性质:

    1.一致性,在Java应用程序执行期间,在同一个Hash算法下,同一个对象的HashCode必定永远相同。

    2.在同一个Hash算法下,当两个对象的HashCode相同,两个对象的equals方法也不一定相同,只能说明在散列的数据结构中,他们存储在同一个位置。

    3.如果两个对象的equals方法相等,那么他们的HashCode必定相同。

    4.重写了Object类中的equals方法,HashCode也尽量重写。

    HashCode的作用

    HashCode的存在就为了查找的快捷,因为HashCode是用来在散列存储结构中确定对象的存储地址,即:使用hashcode来代表对象在hash表中的位置。

    举个例子,我们在内存中要维护1-10000一万个数字,我们可以采用数组,存储,当我存第9001的数字时,需要去遍历前面9000个数字,判断是否是重复,这样的操作会极为耗时,在使用hashcode,假设有200个bucket,hash表中有200个位置,比如要维护数字1,取到的hashcode为1,那就放在第一个bucket中,依次类推,当存储500时,hashcode同样为1,假设第一个位置已经有10个元素,那么只要比较10次,如果没

    有相同,那就放在这个bucket中。

    因此,HashCode就是为了查找便捷而生。

    equals方法和hashcode方法的联系

    通过上面的举例,在散列数据结构的查找中,我们先得出hashcode知道具体的位置,如果该位置上有多个元素,那么逐一比对,即调用equals方法,因此证明了以上提到的观点,

    1.hashcode相同的两个对象,两个对象不一定相同,只能说明两个对象在散列数据结构中存放在同一个位置,

    2.equals相同的两个对象,他们的hashcode必然相同。

    为什么重写Object类中的equals方法尽量重写Object类中的hashcode方法

     1 public class HashCodeTest {
     2 
     3     private Long id;
     4     private String name;
     5 
     6     public Long getId() {
     7         return id;
     8     }
     9     @Override
    10     public boolean equals(Object obj){
    11         if(obj instanceof HashCodeTest) {
    12             HashCodeTest t = (HashCodeTest)obj;
    13             if(id.equals(t.id) && name.equals(t.name())) {
    14                 return true;
    15             }
    16         }
    17         return false;
    18     }
    19 }

    我们重写了Object类中的equals方法,只有两个对象类型相同,并且两个成员属性相同,两个对象才认为是相等。

    1 public static void main(String[] args) {
    2         System.out.println(new HashCodeTest(1L,"tom").hashCode());
    3         System.out.println(new HashCodeTest(1L,"tom").hashCode());
    4         System.out.println(new HashCodeTest(1L,"tom").hashCode());
    5         System.out.println(new HashCodeTest(1L,"tom").hashCode());
    6         System.out.println(new HashCodeTest(1L,"tom").hashCode());
    7 }

    打印出来的结果是:

    1528637575
    1190524793
    472654579
    26117480
    870698190

     equals方法中希望id和name都完全相同则返回true,上述new HashCodeTest中的id和name均相同,如果重写hashcode,就违背了【两个对象的equals相同,hashcode必然相同】的原则,那么我们应该如何处理呢?

    很简单,我们自定义一个id和name保持唯一的算法用来重写HashCode方法。

    下期预告

    这段时间花了大量的精力聊树结构,聊散列结构,都是为了 下期对HashMap原代码的解读打下坚实的基础。谢谢关注。

  • 相关阅读:
    python
    python
    python
    python
    python
    python
    python
    python
    [ThinkPHP] 从一个表中获得栏目对应的ID,从另一个表获得属于这些栏目的文章
    [thinkPHP] buildSql可以查看tp CURD操作对应的SQL
  • 原文地址:https://www.cnblogs.com/sunshine798798/p/9191482.html
Copyright © 2020-2023  润新知