JAVA类中的equals()方法和hashCode()方法的重写

什么情况下需要重写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;    }}

如有错误,请及时指出。谢谢。

当我要取的时候,你淘气的躲开了,

JAVA类中的equals()方法和hashCode()方法的重写

相关文章:

你感兴趣的文章:

标签云: