什么情况下需要重写equals()方法?
在比较两个两个对象时,可以使用==和equals()。前者可以理解为潜比较,既比较对象的引用地址是否相等。后者属于深比较,比较的是两个对象的引用所指向的内容是否相等。
在Object类中已经定义了equals()方法,但该方法是直接采用==操作符实现的,因此子类如果不重写此方法,那么该方法的比较结果和==是一样的。为了方便的比较两个对象的内容是否相等,在定义类的时候一般建议重写此方法。
如何重写equals()方法?
在重写一个类的equals方法之前,要理解两个对象在什么情况下才完全>相等。 重写equals()方法的实例代码如下:
public class Person { private String id; private String name; public String getId() { return id; } public String getName() { return name; } //覆盖equals方法 public boolean equals(Object o) { if(o == null) { return false; } if(this == o) { return true; } if(this.getClass() != o.getClass()) { return false; } Person p = (Person)o; return id.equals(p.getId()) && name.equals(p.getName()); }}
什么情况下需要重写hashCode()方法?
重写了类的equals()方法主要是为了比较两个对象的内容是否相等。hashCode()方法主要返回调用该方法的对象的整数形式的散列码值。
如果一个类重写了equals()方法,通常也有必要重写hashCode()方法。目的是为了维护hashCode()方法的常规协定,该协定声明相等对象必须具有相等的散列码。
hashCode()的常规协定主要有以下几点:
- 在Java应用程序执行期间,在同一对象上多次调用hashCode()方法时,必须返回相同的整数,前提是对象上equals()方法比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致; 如果根据equals()方法比较,两个对象是相等的,那么在两个对象中的每个对象上调用hashCode()方法都必须返回相同的整数结果; 以下情况是必须的:如果根据equals()方法比较两个对象不想等,那么在两个对象中的每个对象上调用hashCode()方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同的整数结果可以提高散列表的性能
实际上,有Object类定义的hashCode()方法确实会针对不同的类返回不同的散列码。(通常是将该对象的内部地址转换成整数来实现的,但是Java编程语言不需要这种实现技巧。)
注意:相等的对象必须有相同的散列码,反之散列码相等则不一定对象相等,而且不想等的对象并不一定需要有不同的散列码。
基于散列法的集合需要使用hashCode()方法返回的散列码值来存储和管理元素,例如HashTable、HashMap、和HashSet等,在使用这些集合时,首先会根据元素对象的散列码值确定其存储位置,然后在根据equals()方法结果判断元素对象是否存在。最后根据判断结果执行不同的处理。
因此,实际应用时,如果重写了equals()方法,那么hashCode()方法也有必要被重写。
如何重写hashCode()方法?
hashCode()方法在重写时,通常按照以下设计原则实现: 1. 把某个非零常数值,例如17,保存在int类型变量result中。 2. 对对象中每一个关键域f(指在equals()方法中考虑的每一个域)参照以下原则处理: – boolean型,计算(f ? 0 : 1); – byte、char、和short型,计算(int); – long型,计算(int)(f^(f>>>32)); – float型,计算Double.doubleToLongBits(double域名称)得到一个long域,再执行long的处理; – 对象类型,递归调用它的hashCode()方法; – 数组域,对其中每个元素调用他的hashCode()方法。 3. 将上面计算的到的散列码保存到int型变量c,再执行result=37*result+c。 4. 返回resul。
重写hashCode()方法的实例代码如下:
public class Unit { private short ashort; private char achar; private byte abyte; private boolean abool; private long along; private float afloat; private double adouble; private Unit aObject; private int[] ints; private Unit[] units; //override equals public boolean equals(Object o) { if(o == null) return false; if(this.getClass() != o.getClass()) return false; Unit u = (Unit)o; return u.ashort == ashort && u.achar == achar && u.abyte == abyte && u.abool == abool && u.along == along && Float.floatToIntBits(u.afloat) == Float.floatToIntBits(afloat) && Double.doubleToLongBits(u.adouble) == Double.doubleToLongBits(adouble) && u.aObject.equals(aObject) && equalsInts(u.ints) && equalsUnits(u.units); } private boolean equalsInts(int[] aints) { return Arrays.equals(ints, aints); } private boolean equalsUnits(Unit[] aUnits) { return Arrays.equals(units, aUnits); } //override hashCode() public int hashCode() { int result = 17; result = 37*result + (int)ashort; result = 37*result + (int)achar; result = 37*result + (int)abyte; result = 37*result + (abool ? 0 : 1); result = 37*result + (int)(along^(along>>>32)); result = 37*result + Float.floatToIntBits(afloat); long tolong = Double.doubleToLongBits(adouble); result = 37*result + (int)(tolong^(tolong>>>32)); result = 37*result + aObject.hashCode(); result = 37*result + intsHashCode(ints); result = 37*result + unitsHashCode(units); return result; } private int intsHashCode(int[] aints) { int result = 17; for(int i : aints) result = 37 * result + i; return result; } private int unitsHashCode(Unit[] aUnits) { int result = 17; for(Unit u : aUnits) result = 37 * result + u.hashCode(); return result; }}
如有错误,请及时指出。谢谢。
当我要取的时候,你淘气的躲开了,