【面试】hashCode与equals两者之间的关系 / == 和equals / 为什么要重写equals方法 / 重写equals /hashcode方法 / 为什么要重写hashCode方法


1、hashCode与equals两者之间的关系

  1. 如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同!!!!
  2. 如果两个对象不同(即用equals比较返回false),那么它们的hashCode值可能相同也可能不同。
  3. 如果两个对象的hashCode相同(存在哈希冲突),那么它们可能相同也可能不同(即equals比较可能是false也可能是true)
  4. 如果两个对象的hashCode不同,那么他们肯定不同(即用equals比较返回false)

2、== 和equals的区别`

== 是运算符,用于比较两个变量是否相等。
`equals`,是Objec类的方法,用于比较两个对象是否相等.
默认Object类的equals方法是比较两个对象的地址,跟==的结果一样

3、为什么要重写equals()方法?

Object类中equals方法比较的是两个对象的引用地址
只有对象的引用地址指向同一个地址时,才认为这两个地址是相等的,否则这两个对象就不相等。
如果有两个对象,他们的属性是相同的,但是地址不同:
这样使用equals()比较得出的结果是不相等的,而我们需要的是这两个对象相等。
因此默认的equals()方法是不符合我们的要求的;
这个时候我们就需要对equals()方法进行重写以满足我们的预期结果。
在java的集合框架中需要用到equals()方法进行查找对象,如果集合中存放的是自定义类型,
并且没有重写equals()方法,则会调用Object父类中的equals()方法按照地址比较,
往往会出现错误的结果,此时我们应该根据业务需求重写equals()方法。

4、重写equals()方法

  • 重写equals方法需要遵循Java如下规则,否则编码行为会难以揣测:
自反性:对于任意的对象x,x.equals(x)返回true(自己一定等于自己)
对称性:对于任意的对象x和y,若x.equals(y)true,则y.equals(x)亦为true
传递性:对于任意的对象x、y和z,若x.equals(y)true且y.equals(z)也为true,则x.equals(z)亦为true
一致性:对于任意的对象x和y,x.equals(y)的第一次调用为true,那么x.equals(y)的第二次、第三次、第n次调用也均为true,前提条件是没有修改x也没有修改y;
对于非空引用x,x.equals(null)永远返回为false
  • 根据以上,上代码
public class Test {
    public static void main(String[] args) {
        Employee employee = new Employee("zhangsan",1);
        Employee employee2 = new Employee("zhangsan",1);
        Person p1 = new Person("zhangsan");

        System.out.println(p1.equals(employee));
        System.out.println(p1.equals(employee2));
        System.out.println(employee.equals(employee2));

        Employee employee3 = new Employee(null,1);
        Employee employee4 = new Employee(null,1);
        Person p2 = new Person(null);
        System.out.println(p2.equals(employee3));
        System.out.println(p2.equals(employee4));
        System.out.println(employee3.equals(employee4));
    }
}

class Person {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Person(String name) {
        this.name = name;
    }
  @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        if(obj == null || getClass() != obj.getClass()){
            return false;
        }
        Person person = (Person) obj;
        if(person.getName() == null | name == null) {
            return false;
        } else {
            return name.equalsIgnoreCase(person.getName());
        }
    }
}
class Employee extends Person {
    private int id;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public Employee(String name, int id) {
        super(name);
        this.id = id;
    }
    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        if(obj == null || getClass() != obj.getClass()){
            return false;
        }
        Employee employee = (Employee) obj;
        if(employee.getName() == null | getName() == null) {
            return false;
        }else {
            return getName().equalsIgnoreCase(employee.getName()) && employee.getId() == id;
        }
    }
}
12false
3true
456false

5、为什么要重写hashCode()方法?

hashCode()方法用于散列数据的快速存储,
HashSet/HashMap/Hashtable类存储数据时都是根据存储对象的hashcode值来进行分类存储的,
一般先根据hashcode值在集合中进行分类,在根据equals()方法判断对象是否相同。
HashMap对象是根据其Key的hashCode来获取对应的Value。
生成一个好的hashCode值能提高HashSet查找的性能,差的hashCode值不但不能提高性能,
甚至可能造成错误。比如hashCode方法中返回常量,
使HashSet的查找效率退化为List集合的查找效率;
hashCode方法中返回随机数,会让查找结果变的不可预测。
一个好的hashCode生成方式是让对象中的关键属性与质数相乘,并将积相加获取。

6、什么时候需要重写hashCode()方法?

在每个类中,在重写 equals 方法的时侯,一定要重写 hashcode 方法
如果不这样做,你的类违反了hashCode的通用约定,这会阻止它在HashMap和HashSet这样的集合中正常工作。

7、重写hashCode()方法:

  • 重写hashCode()方法需要遵循hashCode()协定:
  • 一致性:在Java应用程序执行期间,在对同一对象多次调用hashCode方法时,必须一致地返回相同的整数,前提是将对象进行hashcode比较时所用的信息没有被修改。
  • equals:如果根据equals()方法比较,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode()方法都必须生成相同的整数结果,注:这里说的equals()方法是指Object类中未被子类重写过的equals()方法。
  • 如果根据equals()方法比较,两个对象不相等,那么对这两个对象中的任一对象上调用hashCode方法不一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章