覆写hashCode

在比较两个实例是否相等的时候,一般会覆写equal()方法,而后对类对象的每一成员进行逐一比较,可是JavaSE6规范以下:java

  • 应用程序的执行期间,只要对象的equals方法的比较操做所用到的信息没有被修改,那么对这同一个对象调用屡次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的屡次执行过程当中,每次执行所返回的整数能够不一致。数组

  • 若是两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生一样的整数结果。ide

若是调用父类的equal()方法,且x.equal(y)返回值是true,返回的hashCode值却不一样,所以在覆写equal()方法的同时覆写hashCode()方法。这样才能最大限度地保证,在程序运行过程当中尽量少的出现莫名其妙的错误。函数

再此以前咱们先看一下String类中的hashCode()方法:学习

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

你们可能会以为莫名其妙,hashCode()方法返回的是一个int类型的值,难道这就是所谓的hashCode?不要急,咱们来看一段话,code

一个好的散列函数一般倾向于“为不相等的对象产生不相等的散列码”
对于对象中的每一个关键域f(指equal方法中涉及的每一个域),完成如下步骤:对象

  • 若是该域是boolean类型,则计算(f?1:0);递归

  • 若是该域是byte、char、short或者int计算(int)f;字符串

  • 若是该域是long型,计算(int)(f^(f>>>32));get

  • 若是该域是float类型,计算Float.floatTOIntBits(f);

  • 若是该域是double类型,计算Double.doubleToLongBits(f),而后再根据long型计算获得散列值;

  • 若是该域是一个引用对象,而且该类的equal方法经过递归调用equal的方法来比较这个域,则一样为这个域递归调用hashCode,若是这个域为空,则返回0;
    -若是该域是一个数组,则要把每个元素看成单独的域来处理

按照下面的公式,把上面计算获得的散列码c合并到result中

  • result=31*result+c;

--------------摘自Effective Java

这是EffectiveJava中给出的计算散列码的方法,固然,方法并非惟一,只要咱们保证相同的对象会产生相同的散列码,不一样的得到的散列码不一样就能够了。

如今咱们回过头来看看String类中的hashCode方法

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {//判断hash值不为0,字符串不为空(即长度大于0)
            char val[] = value;//将字符串的值转化为char型数组
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];//遍历char数组中的每个元素经过计算获得hash值
            }
            hash = h;
        }
        return h;
    }

看到这里相信你们已经明了,hash散列码的意义所在,
这里咱们给出一段三个域都是int的hash值计算实例

@Override
    public int hashCode() {
        int result = hashCode;
        //生成对象的惟一散列码
        if (result == 0) {
            result = result * 31 + areaCode;
            result = result * 31 + prefix;
            result = result * 31 + lineNumber;
            hashCode=result;
        }
        return hashCode;
    }

最后,若是你们想深刻学习java的话,建议你们看一看effective java,相信会收获颇丰的。

更多关于java的文章请戳这里:(您的留言意见是对我最大的支持)

个人文章列表

Email:sxh13208803520@gmail.com

相关文章
相关标签/搜索