为什么?
是为了提高效率,采取重写hashcode方法,先进行hashcode比较,如果不同,那么就没必要在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大的效率提高是很明显的,一个很好的例子就是在集合中的使用;
我们都知道java中的List集合是有序的,因此是可以重复的,而set集合是无序的,因此是不能重复的,那么怎么能保证不能被放入重复的元素呢,但靠equals方法一样比较的话,如果原来集合中以后又10000个元素了,那么放入10001个元素,难道要将前面的所有元素都进行比较,看看是否有重复,欧码噶的,这个效率可想而知,因此hashcode就应遇而生了,java就采用了hash表,利用哈希算法(也叫散列算法),就是将对象数据根据该对象的特征使用特定的算法将其定义到一个地址上,那么在后面定义进来的数据只要看对应的hashcode地址上是否有值,那么就用equals比较,如果没有则直接插入,只要就大大减少了equals的使用次数,执行效率就大大提高了。
同时也是为了保证同一个对象,保证在equals相同的情况下hashcode值必定相同,如果重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的(因为equal都是根据对象的特征进行重写的),但hashcode确实不相同的。
举例说明: 现在定义一个Student类和一个测试类。Student包括姓名和年龄。
public class Student { String Name; int age; public Student(String Name,int age){ this.Name = Name; this.age = age; }
public class Test { public static void main(String[] args) { Student s1 = new Student("小方",12); Student s2 = new Student("小方",12); System.out.println(s1.equals(s2)); } }
当我们重写equals后
public class Student { String Name; int age; public Student(String Name,int age){ this.Name = Name; this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(Name, student.Name); } }
总结:
-
hashCode主要用于提升查询效率,来确定在散列结构中对象的存储地址;
-
重写equals()必须重写hashCode(),二者参与计算的自身属性字段应该相同;
-
hash类型的存储结构,添加元素重复性校验的标准就是先取hashCode值,后判断equals();
-
equals()相等的两个对象,hashcode()一定相等;
-
反过来:hashcode()不等,一定能推出equals()也不等;
-
hashcode()相等,equals()可能相等,也可能不等。