重写了equals()为什么要重写hashCode()方法

java中任何一个类都会继承Object类,在Object的方法中就有,equals()方法和hashCode()方法,因此任何一个类都默认有这两个方法。在默认情况下。equals与”==”相等。即比较两个引用对象是否为一个对象。

        Object ob1 = new Object();
        Object ob2 = new Object();
        System.out.println(ob1 == ob2);
        System.out.println(ob1.equals(ob2));
 
 
  • 1
  • 2
  • 3
  • 4

运行结果为: 
false 
false 
但是在很多类中已经重写了equals()方法,例如String,Integer,Character…等类型。已经不是比较两个引用是否为一个对象,而是比较逻辑上的值是否相等,此时”==”与equals()是两个概念。

        String s1 = new String("micro");
        String s2 = new String("micro");
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));
 
 
  • 1
  • 2
  • 3
  • 4

运行结果为: 
false 
true 
因为此时s1与s2的值是相等的。因此返回true 
hashCode()方法是为任何一个对象生成一个哈希码,相同(逻辑上认为)的对象应该生成相同的哈希码,Java内置的求出的哈希码是基于存储地址的一个映射关系,保证了对象的哈希码的一一对应关系。散列存储,即是根据一个关键字找到对应的对象,存在对应的哈希表里,关键字最好是分散的,如果算法设计不合理即产生冲突,会根据冲突算法插入其他地方,但是这样会降低哈希表的效率。因此设计一个好的算法对于散列存储是十分重要的。 
下面定义一个对象:

class Student
{
    int sno;
    String name;
    Student(int sno,String name)
    {
        this.sno = sno;
        this.name = name;
    }
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在Main中如下调用:

        Student s1 = new Student(1,"micro");
        Student s2 = new Student(1,"micro");
        Set<Student> set = new HashSet();
        set.add(s1);
        set.add(s2);
        System.out.println(set.size());
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行结果为: 

因为Jvm利用Object的hashCode()方法算出的两个对象不是一个对象。所以都添加进去了。但是我们认为s1与s2应该是相同的对象。那这该怎么解决呢。在Jvm中,插入哈希表的过程是先比较对应对象的哈希码,如果哈希码相同,再比较euqual()是否为true,如果为true则不插入,如果不为true则按照哈希冲突的原则插入到其他地方。 一个好的散列算法可以利用哈希码大大降低调用equals()方法的次数从而提高处理效率。 
要让哈希表存储进去的对象不相同。 
因此先让哈希码筛选一次如果通过筛选再让equals方法决定是否为相同的对象。也就是说得equals相等的对象hashCode()一定相等,hashCode相等的对象equals方法不一定相等。所以重写了equals方法的对象一定要重写hashCode(),否则hashCode()不相等根本就没有equals比较的机会就会让euquals相等(我们认为相等)的对象也插入到哈希表。 
对Student进行重写:

class Student
{
    int sno;
    String name;
    Student(int sno,String name)
    {
        this.sno = sno;
        this.name = name;
    }
    @Override
      public boolean equals(Object obj) {
        if(obj instanceof Student)
        {
            return (this.sno == ((Student)obj).sno && this.name == ((Student)obj).name);
        }
        else
        {
            return false;
        }

    }
    @Override 
    public int hashCode()
    {
     return sno + 10;
    }
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在main中进行插入:

        Student s1 = new Student(1,"micro");
        Student s2 = new Student(1,"micro");
        Set<Student> set = new HashSet();
        set.add(s1);
        set.add(s2);
        System.out.println(set.size());
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行结果为: 

此时如果不重写哈希码则会产生不同的哈希码,直接插入s2。但是重写了哈希码,首先比较哈希码发现相等,然后用equals方法发现也相等。因此不插入s2。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值