Java原始碼之String的HashCode方法

程式碼實習僧發表於2020-12-20

首先看下String類的HashCode原始碼,詳見對應語句後的註釋:

public int hashCode() {
        // The hash or hashIsZero fields are subject to a benign data race,
        // making it crucial to ensure that any observable result of the
        // calculation in this method stays correct under any possible read of
        // these fields. Necessary restrictions to allow this to be correct
        // without explicit memory fences or similar concurrency primitives is
        // that we can ever only write to one of these two fields for a given
        // String instance, and that the computation is idempotent and derived
        // from immutable state
        int h = hash;	 //String初始化時hash值預設為零
        if (h == 0 && !hashIsZero) {   //避免重複計算hash值。String物件初始化時,h=hash預設為0,hashIsZero預設為false
            h = isLatin1() ? StringLatin1.hashCode(value)	//根據字元編碼呼叫不同的計算方法,value是實現String的字元陣列
                           : StringUTF16.hashCode(value);
            if (h == 0) {					
                hashIsZero = true;			//如果計算出的h值為0,則將hashIsZero賦值為true
            } else {
                hash = h;					//計算出的h值不為0時,將h賦值為hash
            }
        }
        return h;
    }

下面看下 StringLatin1.hashCode(value)和StringUTF16.hashCode(value)方法的原始碼:

 //StringLatin1.hashCode(value)
 public static int hashCode(byte[] value) {
        int h = 0;
        for (byte v : value) {
            h = 31 * h + (v & 0xff);		//根據字元計算hash值
        }
        return h;
    }
 //StringUTF16.hashCode(value)
 public static int hashCode(byte[] value) {
        int h = 0;
        int length = value.length >> 1;		//將length值除以2,很少呼叫這個方法
        for (int i = 0; i < length; i++) {	//根據字元計算hash值
            h = 31 * h + getChar(value, i);
        }
        return h;
    }

Latin1是ISO-8859-1編碼的別名,大家可以看到hash值是根據“h = 31 * h + ASCII碼”遞迴所有字元陣列求得,下面舉個簡單的例子:

public class StringHashCode {
    public static void main(String[] args){
        System.out.println("編碼方式:"+Charset.defaultCharset().name());
        String s1 = "a";
        String s2 = "s";
        String s3 = "as";
        System.out.println("a的hashCode:"+s1.hashCode());
        System.out.println("s的hashCode:"+s2.hashCode());
        System.out.println("as的hashCode:"+s3.hashCode());
    }
}

結果為:
在這裡插入圖片描述
如有錯誤,敬請指正

相關文章