hashcode 和 equals

来源:互联网 发布:抓小三软件 编辑:程序博客网 时间:2024/06/10 22:29

1、当集合添加新的元素时,先调用这个元素的hashCode()方法,定位到它应该存放的物理位置上。如果这个位置上没有元素,就直接存储在这个位置上,不用再进行比较了;如果这个位置上已经存在了元素,就再调用它的equals()方法与新元素进行比较,相同的话就不存储了,不同的话就散列到其他的位置上。

2、java对equals()方法和hashCode()方法是这样规定的:
  如果两个对象相等,则他们的hashCode值一定相等;
  如果两个对象的hashCode相等,他们并不一定相等。

3、何时需要重写hashcode?

首先,equals()和hashCode()两个函数是紧密结合的,必须同时实现,不能单独重写其中的一个。

在下面的情况下需要重写(其他情况下不需要重写):
1)将一个对象A放入到另一个集合对象B中;
2)使用对象A占作为集合对象B的key,支持对对象B查找元对象、是否容纳和删除等操作;

如果涉及的对象类型不使用于集合对象,就没有必要再设计这两个函数;

当一个对象类型作为集合对象的元对象时(1)),这个对象应该拥有自己处理equals(),equals()先要查null和是否是同一类型。查同一类型是为了避免出现ClassCastException这样的异常给丢出来。查 null是为了避免出现NullPointerException这样的异常给丢出来;

如果你的对象里面容纳的数据过多,那么这两个函数 equals()和hashCode()将会变得效率低。如果对象中拥有无法serialized的数据,equals()有可能在操作中出现错误。想象 一个对象x,它的一个整型数据是transient型(不能被serialize成二进制数据流)。然而equals()和hashCode()都有依靠 这个整型数据,那么,这个对象在serialization之前和之后,是否一样?答案是不一样。因为serialization之前的整型数据是有效的 数据,在serialization之后,这个整型数据的值并没有存储下来,再重新由二进制数据流转换成对象后,两者(对象在serialization 之前和之后)的状态已经不同了。


4、设计hashcode

[1]把某个非零常数值,例如17,保存在int变量result中;
[2]对于对象中每一个关键域f(指equals方法中考虑的每一个域):
    [2.1]boolean型,计算(f ? 0 : 1);
    [2.2]byte,char,short型,计算(int);
    [2.3]long型,计算(int) (f ^ (f>>>32));
    [2.4]float型,计算Float.floatToIntBits(afloat);
    [2.5]double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行[2.3];
    [2.6]对象引用,递归调用它的hashCode方法;
    [2.7]数组域,对其中每个元素调用它的hashCode方法。
[3]将上面计算得到的散列码保存到int变量c,然后执行 result=37*result+c;
[4]返回result。

 

5、设计equals

[1]使用instanceof操作符检查“实参是否为正确的类型”。
[2]对于类中的每一个“关键域”,检查实参中的域与当前对象中对应的域值。
    [2.1]对于非float和double类型的原语类型域,使用==比较;
    [2.2]对于对象引用域,递归调用equals方法;
    [2.3]对于float域,使用Float.floatToIntBits(afloat)转换为int,再使用==比较;
    [2.4]对于double域,使用Double.doubleToLongBits(adouble) 转换为int,再使用==比较;
    [2.5]对于数组域,调用Arrays.equals方法。

 

6、实例

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;    private String name;     public boolean equals(Object o) {       if (!(o instanceof Unit))           return false;       Unit unit = (Unit) o;       return unit.ashort == ashort              && unit.achar == achar              && unit.abyte == abyte              && unit.abool == abool              && unit.along == along              && Float.floatToIntBits(unit.afloat) == Float.floatToIntBits(afloat)              && Double.doubleToLongBits(unit.adouble) == Double.doubleToLongBits(adouble)              && unit.aObject.equals(aObject)              && equalsInts(unit.ints)              && equalsUnits(unit.units);    }     private boolean equalsInts(int[] aints) {       return Arrays.equals(ints, aints);    }     private boolean equalsUnits(Unit[] aUnits) {       return Arrays.equals(units, aUnits);    }     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);       result = 37 * result + (name != null ? name.hashCode() : 0);  // 上面也可以这么写       return result;    }     private int intsHashCode(int[] aints) {       int result = 17;       for (int i = 0; i < aints.length; i++)           result = 37 * result + aints[i];       return result;    }     private int unitsHashCode(Unit[] aUnits) {       int result = 17;       for (int i = 0; i < aUnits.length; i++)           result = 37 * result + aUnits[i].hashCode();       return result;    }}

 

原创粉丝点击