Java中==、equals、hashcode的区别?为什么重写hashcode还要重写equals?

1.Java中==、equals、hashCode的区别?

1.1基本数据类型使用==与equals


  • java基本数据类型包括:byte、short、int、long、float、double、boolean、char
  • 基本数据类型使用"=="比较内容是否相同,不能使用equals
int d = 2;
int e = 3;
int f = 3;
System.out.println(d == e);//2与3比较
System.out.println(e==f);//3与3比较
//System.out.println(d.equals(f));基本数据类型中没有equals方法
false
true

1.2引用数据类型==与equals


  • 引用数据类型使用"=="比较栈内存地址是否相同
String g = new String("aw1");
String h = new String("aw");
String i = new String("aw");
System.out.println(g==h);//对象g的地址与对象h的地址比较
System.out.println(h==i);//对象h的地址与对象i的地址比较
false
false
  • 引用数据类型使用equals先比较对象类型是否相同,再比较堆中对象的内容是否相同。
System.out.println(h.equals(i));//对象h的内容aw与对象i的内容aw比较
System.out.println(h.equals(g));///对象h的内容aw与对象g的内容aw1比较
true
false
  • 小坑:
  • 包装类型使用"=="与上述说的有些不一样,从源码可看出,包装类型的值如果在范围内,会进行缓存,后面需要使用该对象,直接可以从缓存中取,不会再new对象。但在范围之外,会在堆上产生新对象,并不会复用已有对象。包装类型使用equals与引用数据类型一样。
public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
Integer ina = 1;
Integer inb = 1;
Integer inc = 1000;
Integer ind = 1000;

System.out.println(ina == inb);//在-128~127范围内,b直接从缓存中取,地址一样
System.out.println(inc == ind);//超过127,会产生新对象d,地址不一样
System.out.println(ina.equals(inb));//equals之比较类型和对应内容是否一样,1与1
System.out.println(inc.equals(ind));//1000与1000
true
false
true
true

1.3hashCode


  Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。判断元素是否重复使用Object.equals方法,但是每增加一个元素,就需要遍历整个集合,效率会很低。
  于是,Java采用了哈希表的原理,当集合要添加新的元素时,先调用这个元素的hashCode方法,就能定位到它应该放置的哈希表中对应位置。 如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存,不相同就散列其它的地址。这样一来实际调用equals方法的次数就大大降低了。

  • 基本类型包装类hashCode的方法实现
    https://blog.csdn.net/realwongp/article/details/88901418

2.为什么要重写equals还要重写hashCode?

  • 在HashMap中,如果要比较key值是否相等,要同时使用equals和hashCode,因为自定义类的hashCode方法继承于Object类,hashCode码为默认的内存地址,这样即便有相同含义的两个对象,比较也是不同的。

  • HashMap中比较key值是先求出key的hashCode码,比较其值是否相等。若相等,再比较equals(),若为true则认为是相等的,若为false则认为是不相等的。如果只重写的hashCode()方法,不重写equals()方法,那么只是对它们内存地址的比较,所以要两个方法一起重写。

  • 关于hashCode方法,一致的约定是:
      1.重写了euqals方法的对象必须同时重写hashCode()方法。
      2.如果2个对象通过equals调用后返回是true,那么这个2个对象的hashCode方法也必须返回同样的int型散列码
      3.如果2个对象通过equals返回false,他们的hashCode返回的值允许相同,最好是不相同。

  • 以下为Student类,只重写了hashCode(),没有重写equals(),虽然s1与s2内容相同且hashCode相同,但是equals()比较的是s1与s2内存地址是否一样,所以返回了false。如上约定3所言。

public class Student {
    public String name;
    public int age;
    public double weight;
    public boolean isMarry;

    public Student(String name, int age, double weight, boolean isMarry){
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.isMarry = isMarry;
    }
    @Override
    public int hashCode(){
            int result =  name != null ? name.hashCode():0;
            result = 31*result + age % 10;
            Long temp = Double.doubleToLongBits(this.weight);
            result = 31*result + (int)(temp ^ (temp >>>32));
            result = 31*result + (isMarry ? 1:0);
            return result;
    }
public static void main(String[] args) {
        Student s1 = new Student("hihi",2,52.5,true);
        Student s2 = new Student("hihi",2,52.5,true);
        Student s3 = new Student("hihisas",4,52.5,false);
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
        System.out.println(s3.hashCode());
        System.out.println(s1.equals(s2));
        System.out.println(s2.equals(s3));
    }
-6555007
-6555007
-2036969151
false
false
  • 重写equals()后,如上约定2所言,equals返回的是true,那么两个对应的hashCode值必须相等。
    @Override
    public boolean equals(Object object) {
        Student student = (Student) object;
        if(student == null ){
            return false;
        }else if(this.name==student.name&&this.age==student.age&&this.isMarry==student.isMarry&&this.weight==student.weight){
            return true;
        }
        return false;
    }
-6555007
-6555007
-2036969151
true
false

以上仅为学习笔记,如有错误,请多指教!

  • 参考
    https://www.cnblogs.com/kexianting/p/8508207.html
    https://www.cnblogs.com/whgk/p/6071617.html
    https://www.jianshu.com/p/b443ad1d62de

你可能感兴趣的:(Java中==、equals、hashcode的区别?为什么重写hashcode还要重写equals?)