最近有小夥伴在使用java1.6的jdk時,發現1.6版本switch ..case 不支持字符串類型。
首先,升級jdk版本是不可能的,比較老項目,只能用1.6的。
比如下面這樣寫,jdk1.6不支持。
於是有個小夥伴說,這樣寫不就可以了?
的確,這樣寫是可以的,但並不建議。
首先,需要理解一下hashCode方法的含義,以及知道不同String,調用hashCode方法返回的值可能是相同的,比如"Aa"和"BB"的hashCode方法返回的都是2112.這時如果用在這裡,就有問題了。
我們再來看看String的hashCode方法源碼:
1、為什麼有個常數31作為生成hashCode算法的一部分?
大家都知道,計算機的乘法涉及到移位計算。當一個數乘以2時,就直接拿該數左移一位即可!選擇31原因是因為31是一個質數!
所謂質數是指在一個大於1的自然數中,除了1和此整數自身外,沒法被其他自然數整除的數。在存儲數據計算hash地址的時候,我們希望儘量減少有同樣的hash地址,所謂「衝突」。如果使用相同hash地址的數據過多,那麼這些數據所組成的hash鏈就更長,從而降低了查詢效率!
所以在選擇係數的時候要選擇儘量長(31 = 11111[2])的係數並且讓乘法儘量不要溢出(如果選擇大於11111的數,很容易溢出)的係數,因為如果計算出來的hash地址越大,所謂的「衝突」就越少,查找起來效率也會提高。
31的乘法可以由i*31== (i<<5)-1來表示,現在很多虛擬機裡面都有做相關優化,使用31的原因可能是為了更好的分配hash地址,並且31隻佔用5bits!在java乘法中如果數字相乘過大會導致溢出的問題,從而導致數據的丟失. 而31則是素數(質數)而且不是很長的數字,最終它被選擇為相乘的係數。
2、我們再來看看val[i]其實就是字符串裡的字符,當與整數相加時,會轉換成一個整數。
對於字符串"Aa",hash = 0+65 + 31*65 + 97 = 2112
對於欄位串"BB",hash = 0+66 + 31*66 +66 = 2112;
所以不同的字符有可能生成相同的hashCode,在swicht..case裡使用hashCode的寫法,是不建議的。
當然,當字符比較長時,衝突的概率是比較低的。