java String hashCode遇到的坑


在進行數據交換時,如果主鍵不是整型,需要對字符串,或聯合主鍵拼接為字符串,進行hash,再進行取模分片,使用的是String自帶的hashCode()方法,本來是件很方便的事,但是有些字符串取hashCode竟然是負數,使得分片為負數,找不到對應的分片,我們先看一下String 生成hashCode的代碼:

 /**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    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;
    }

主要是根據字符串中字符的ascii碼值來計算的,即 31  * hash + 字符的ASCII碼值,int型的值取值范圍為Integer.MIN_VALUE(-2147483648)~Integer.MAX_VALUE(2147483647),所以如果字符串比較長,計算的數值就可能超出Integer.MAX_VALUE,造成數值溢出,值變成負數

幾種比較極端的字符串hashCode值:

        String hashStr0 = "35953305172933/";
        System.out.println(hashStr0.hashCode());            // 2147483647   Integer.MAX_VALUE
        System.out.println(Math.abs(hashStr0.hashCode()));  // 2147483647   Integer.MAX_VALUE
        System.out.println("-------------------");
        String hashStr = "359533051729330";
        System.out.println(hashStr.hashCode());             // -2147483648  Integer.MIN_VALUE
        System.out.println(Math.abs(hashStr.hashCode()));   // -2147483648  Integer.MIN_VALUE
        System.out.println("-------------------");
        String hashStr2 = "56800004874";
        System.out.println(hashStr2.hashCode());            // -2082984168
        System.out.println(Math.abs(hashStr2.hashCode()));  // 2082984168
        System.out.println("-------------------");
        String hashStr3 = "";
        System.out.println(hashStr3.hashCode());            // 0
        System.out.println(Math.abs(hashStr3.hashCode()));  // 0
        System.out.println("-------------------");

對於字符串“359533051729330”的hashCode為Integer.MIN_VALUE,我們使用取絕對值還是超出Integer.MAX_VALUE,還是Integer.MIN_VALUE,所以針對這種極端情況是不可用的

要想利用hashCode為非負數,可以Integer.MAX_VALUE和與操作,這樣最大正整數的符號位為0,與任何數與操作都是0,即是正數

int hash = str.hashCode() & Integer.MAX_VALUE;

 

 

 

2147483647 Integer.MAX_VALUE


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM