• Java String类的hashCode()函数


    1 ==和equals()

    ==比较两个对象是否指向同一个内存地址。

    equals()方法判断两个对象的值是否相等。

    2 String.equals()

    String类对equals()方法重写如下:

     1     public boolean equals(Object anObject) {
     2         if (this == anObject) {
     3             return true;
     4         }
     5         if (anObject instanceof String) {
     6             String anotherString = (String) anObject;
     7             int n = value.length;
     8             if (n == anotherString.value.length) {
     9                 char v1[] = value;
    10                 char v2[] = anotherString.value;
    11                 int i = 0;
    12                 while (n-- != 0) {
    13                     if (v1[i] != v2[i])
    14                             return false;
    15                     i++;
    16                 }
    17                 return true;
    18             }
    19         }
    20         return false;
    21     }

    String、StringBuffer及StringBuilder是两两不equals()的。如果需要,使用contentEquals()。

    3 String.hashCode()

    判断对象值是否相等时,会先判断其hashCode是否相等。如果hashCode不相等,则equals()方法返回false;不然,再进行比较。

    jvm默认hashCode不相等,则对象值也不相等。其逆反命题是:若对象值相等,则其hashCode也相等。

    重写equals()时,必须也重写hashCode()。并且需要保证,值相等的对象,有相同的hashCode。

     1     public int hashCode() {
     2         int h = hash;
     3         if (h == 0 && value.length > 0) {
     4             char val[] = value;
     5 
     6             for (int i = 0; i < value.length; i++) {
     7                 h = 31 * h + val[i];
     8             }
     9             hash = h;
    10         }
    11         return h;
    12     }

    hash值的计算方式大概是这个样子:

    hash(k) = mix(k) mod m

    String类中:

    mix(k) = 31 * k

    这里魔法数字选择31的原因是:

    * 这里hash是int型,则有m = 2^p。这里魔法数字为2的倍数时,除String对象的最后一位,其他位的信息均不能hash到奇数桶中。也就是说,String对象最后一位的分布决定了哈希函数的分布。由此可推断,魔法数字不该与m有公约数。

    * 素数可以使得散列的分布更加均匀。

    * 乘以31计算简单,只需一次移位一次减法操作。

    * 31是大于26的素数中,最小的。越小,溢出的可能性就越低。

    这里1、3、4的含义是自现的,而2,目前还没有明确的证明。

    个人觉得,只要是奇数,都是可行的。

  • 相关阅读:
    acdream 1017: Fast Transportation 网络流层次图
    centos5的kernel source
    Linux内核源代码的阅读及相关工具介绍(转)
    gcc生成静态库和动态库(转)
    写一篇大家一看就会的教程《JNI初步》(转)
    jni.h
    5分钟学用Lucene
    (VC2005) picture 控件显示16*16的Icon
    (VC/MFC)通过结构体传递参数给线程
    (VC2005)MFC中添加控件的成员变量.
  • 原文地址:https://www.cnblogs.com/yanyichao/p/4493166.html
Copyright © 2020-2023  润新知