Java的equal,hashcode,compareTo方法理解

java的自定义对象,一般是不可比较的,但是我们很多时候需要对自定义的对象进行排序,去重等操作,这就需要我们自己去写comparable接口了。

comparable接口简介

最重要是实现int compareTo(T o)这个方法,形参是待比较对象T,i是判断对象是否相等的。

  • i=0,x和y相等
  • i>0,x>y(y是待比较对象)
  • i<0,x<y

实际取决与compareTo方法体中,this和object的位置。

compareTo方法实现

public int compareTo(Object o){
Student s = (Student)(o);
return this.ranking - s.ranking;
}

注意这里this.ranking-s.ranking,这个顺序与上面的i的位置是对应的。如果是s.ranking-this.ranking的话,i>0那么x<y了(y是待比较对象)。


重写equal方法的时候,必须重写hashcode方法。hashCode 方法的常规协定声明相等对象必须具有相等的哈希码。如下:

  • 当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true
  • 当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false,

这样如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true,但不重写hashcode,那么我们再new一个新的对象,当原对象equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,如在存储散列集合时(如Set类),将会存储了两个值一样的对象,导致混淆,因此,就也需要重写hashcode()

重写equal方法,只需要按照《Effective Java》推荐的步骤,即可。

//判断引用指向是否相同
if(other==this){return true;}
//判断是否是该类型的对象
if(!(other instanceof Student)){return false;}
//比较自定义的数据域
Student student = (Student)other;
return student.name.equals(name)&&student.age==age;

重写hashcode方法: 要保证Coder对象中所有的成员都能在hashCode中得到体现

public int hashCode() {
//这个数值可以自己定义
int result = 17;
//体现一下对象的所有属性
result = result * 31 + name.hashCode();
result = result * 31 + age;
return result;
}

hashCode()方法就是为哈希表服务的. 当我们在使用形如HashMap, HashSet这样前面以Hash开头的集合类时,hashCode()就会被隐式调用以来创建哈希映射关系


总结,自定义类要重写equals方法来进行等值比较,自定义类要重写compareTo方法来进行不同对象大小的比较,重写hashcode方法为了将数据存入HashSet/HashMap/Hashtable类时进行比较

讲得比较好的博客