[Java] hashCode()和equals()方法的重写

关于hashCode()方法和equals()方法的重写

  • 我们向Set集合中添加的对象,这个对象的所在类中一定要重写equals()方法和hashCode()方法
    • 这里我们不一定要重写hashCode()方法,因为我们的TreeSet类中我们我们判断数据是否重复是通过Comparable接口中的compareTo()方法或者是通过Comparator接口中的compare()方法的返回值来判断的,这个时候我们并没有使用到hashCode()方法,但是equals()方法我们一定要重写,因为我们要去判断我们使用有的方法时就要通过equals()方法进行判断
  • 其实我们推荐在重写equals()方法的时候就一并重写hashCode()方法

java官方提示:我们的hashCode()方法应该时刻和equals()方法保持一致性

这里的一致性:指的就是我们相同的对象具有相同的哈希码值

  • 我们的Object类中的hashCode()方法我们就可以看作是一个随机值函数,随机产生一个哈希码值
  • 我们的Object 类中的hashCode()方法和Object类中的equals()方法保持一致
    • 也就是地址不同的两个对象,那么这两个对象的哈希码值也不同

重写equals(Object o)方法时的基本原则:

  1. 重写equals方法的时候要注意一定要将我们的参数对象一定要考虑为空的情况

    • 这里如果我们没有将我们的参数对象为空的情况排除在外,那么这个时候我们就可能会去用这个空的对象去调用一个数据进行比较,这个时候就会出现空指针异常

    eg:

    package 面向对象练习;
    
    

import java.util.Objects;

public class Cat {
private String name;
private int age;
public Cat(){

   }
   public Cat(String name,int age ){
       this.name=name;
       this.age=age;
   }
   
   @Override
   public boolean equals(Object o) {
       if (this == o) return true;
       if (getClass() != o.getClass()) return false;
       /* 
       这个时候只是排除了我们的参数对象和模板类的类型和我们的Cat类型不一致的情况,但是并没有排除空指针的可能,这个时候
       如果参数对象为null,那么这个时候就会出现空指针异常
        */
       Cat cat = (Cat) o;
       return age == cat.age &&
               Objects.equals(name, cat.name);
   }

}
class Test{
public static void main(String[] args) {
Cat cat = new Cat(“小橘”,3);
cat.equals(null);
}
}

   



2. 重写equals()方法一定要考虑参数对象类型和我们的本类(也就是调用类)不一致的情况

   * 如果不一致就要排除,如果参数对象和我们的本类的类型都不一致,那么我们的向下转型时就会出现一个类型转换异常(ClassCastException)

   eg:

   ```java
   package equals方法;
   
   import java.util.Objects;
   
   public class Cat2 {
       private String name;
       private int age;
   
       public Cat2() {
   
       }
   
       public Cat2(String name, int age) {
           this.name = name;
           this.age = age;
       }
   
       @Override
       public boolean equals(Object o) {
           if (this == o) return true;
           if (o==null) return false;
           /*
           这个时候我们只是将我们参数为空时出现空指针的情况排除在外了,这个时候如果我们的本类对象调用equals()方法和
           其他类的对象进行比较时就会出现类型转换异常(ClassCastException)
            */
           Cat2 cat = (Cat2) o;
           return age == cat.age &&
                   Objects.equals(name, cat.name);
   
       }
   }
   class Test2{
       public static void main(String[] args) {
           Cat2 cat = new Cat2("小橘",3);
           cat.equals(null);
       } 
   }
  1. 最后就是我们重写equals()方法的时候一定要先从特殊情况出发,先排除特殊情况,这样可以提高程序的执行效率

重写hashCode()方法的基本原则:

  1. 在程序运行时,同一对象多次调用hashCode()方法,应该返回相同的值
  2. 当两个对象的equals()方法比较返回true时,则两个对象的hashCode()方法的返回值也相等
  3. 对象中作equals()方法比较的Field(字段,属性),都应该用来计算hashCode()的返回值

eg:这里我们举一个重写了equals()方法并且重写了hashCode()方法并且保持一致性的例子

package com.ffyc.javaoop.day19;

import java.util.Objects;

public class Dog {
    private String name;
    private int age;
    public Dog(){
        
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Dog dog = (Dog) o;
        return age == dog.age &&
                Objects.equals(name, dog.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
  • 在这里我们重写equals()方法时通过name属性和age属性判断,我们的hashCode()方法也是通过name属性和age属性进行计算
    • 这样就可以保证我们的equals()方法和hashCode()方法保持一致

我们可以发现我们使用集成开发工具(比如使用IDEA或者使用eclipse生成的hashCode()方法中都有一个31我们的int类型的数值),这里为什么是31,这个31是怎么来的?

  1. 我们选择系数的时候要选择尽量大的系数,因为如果计算出来的hash地址越大,那么冲突的概率就会越小,使用hashCode()对散列结构的中的元素进行查找时的效率也会提高
  2. 并且我们的31只用5个bit(位)进行存储,做了乘法运算之后出现造成数据溢出的概率也比较小
  3. 并且31可以使用2<<5-1进行表示,我们使用位运算进行运算的效率要高,这个时候也就提高了hashCode()方法的使用效率
  4. 并且31是一个素数,使用素数去乘的好处是我们使用素数乘以一个数,那么最终计算出来的结果只能被这个素数和另一个乘数来整除(这里我们没有算计算的结果和1),这样也可以减小冲突的概率
### 回答1: 在Java中,hashcodeequals方法是用于比较对象的重要方法。当我们需要比较两个对象是否相等时,就需要重写这两个方法hashcode方法是用于获取对象的哈希码,它返回一个int类型的值。在重写hashcode方法时,我们需要保证相等的对象返回相同的哈希码,这样才能保证在使用哈希表等数据结构时,对象能够正确地被存储和查找。 equals方法是用于比较两个对象是否相等,它返回一个boolean类型的值。在重写equals方法时,我们需要保证相等的对象返回true,不相等的对象返回false。通常情况下,我们需要比较对象的属性值是否相等来判断两个对象是否相等。 需要注意的是,当我们重写equals方法时,也需要同时重写hashcode方法,否则在使用哈希表等数据结构时,可能会出现错误。 ### 回答2: hashcodeequals都属于Object类中的方法,而在Java中,许多数据结构都需要根据对象的hashcodeequals方法来判断某个对象在数据结构中的位置和是否相等。因此,我们通常需要重写这两个方法来满足自己的需求。 hashcode方法是返回某个对象的哈希码,它的作用是在HashMap、HashSet等数据结构中对对象进行分类。如果两个对象使用equals方法比较返回true,那么它们的hashcode方法必须返回相同的值,否则可能会造成数据结构失效导致数据无法取出。如果两个对象的hashcode值相等,但是使用equals方法比较返回false,这种情况称为哈希冲突。我们可以通过提高哈希冲突的概率来提高数据访问效率,例如优化哈希函数或者增大哈希表的容量。 equals方法是用来比较两个对象是否相等,我们可以根据对象中的属性来自定义相等的规则。常见的重写方式是比较对象中每个属性的值是否相等。需要注意的是,我们需要保证equals方法满足自反性、对称性、传递性和一致性等特征,否则可能导致数据结构错误或程序异常。 在Java中,通常当我们自定义一个类时,需要重写这两个方法以保证程序的正确性和程序运行效率。重写方法要根据实际情况来选择,我们可以根据每个对象的属性来计算hashcode,也可以使用一些第三方框架来自动实现equalshashcode方法,例如lombok、Apache Commons等。无论选择哪种方式,我们都要保证程序正确性和运行效率的平衡。 ### 回答3: Java中的hashcodeequals方法是常用的对象方法,它们的作用是对对象进行操作和比较。在使用Java集合类时,如HashMap、HashSet、HashTable等都会用到hashcodeequals方法hashcode方法是Object类中定义的方法,它返回对象的哈希码值。哈希码值是一个int类型的整数,它通过将该对象的内部地址转换成一个整数来计算。如果需要使用自定义的容器或自定义的集合类时,需要重写hashcode方法以提高容器性能。 equals方法也是Object类中定义的方法,它用于比较两个对象是否相等。当需要判断两个对象是否相等时,就需要重写equals方法。通常情况下,equals方法比较的是对象的属性值,所以在实现equals方法时需要考虑对象的属性。 在重写equals方法时,需要注意以下几点: 1. 重写equals方法时,需要保证它遵循自反性、对称性、传递性和一致性这四个基本原则。 2. 对象相等的条件是对象的属性值相等,而不是内存地址相等。 3. 在比较对象属性时,需要避免空指针异常。 4. 当对象中包含集合类型的属性时,在比较集合类型属性时需要递归比较每个元素。 当对hashcodeequals方法进行重写时,需要同时重写。如果两个对象的equals方法返回true,那么它们的hashcode也应该相同。同时,如果两个对象的hashcode相同,那么它们不一定相等,需要通过equals方法再次比较。 总之,对hashcodeequals方法重写可以提高Java容器的性能,也可以确保对象比较的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值