Why hashcode 31?

Posted 高爽 Coder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Why hashcode 31?相关的知识,希望对你有一定的参考价值。

       本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/21328203,转载请注明。
       前几天被人问到了hashcode如何实现,说实话,真的是没有自己写过,通常情况下都会通过IDE自动生成,惭愧。今天研究了下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;
    

       核心的算法就是中间的for循环,假如字符串是"abcde",那最终的hash值应该是31(31(31(31a+b) + c) + d) + e,扩号展开为a*31^4+b*31^3+c*31^2+d*31^1+e*31^0,设字符串的长度为n,那最终的计算公式为:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],这实际上就是31进制数转成10进制数的算法。那为什么要用31作为基数呢?
       我想可能有几点原因:31首先是一个素数,与素数相乘运算后,能降低hashcode碰撞的概率;31其次是一个特殊的值(32-1),32的二进制是100000,31的二进制是011111,31*N = N << 5 - N,运算速度会快。
       普通类覆盖hashCode方法也可以使用类似的算法,如:

@Override
	public int hashCode() 
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((firstname == null) ? 0 : firstname.hashCode());
		result = prime * result
				+ ((lastname == null) ? 0 : lastname.hashCode());
		result = prime * result
				+ ((nickname == null) ? 0 : nickname.hashCode());
		return result;
	
       属性如果是引用类型,要与其hashCode运算,属性如果是byte、short、int类型,要与其值运算,属性如果是float、double、long,要经过特殊运算,可以参考对应封装类的hashCode方法实现。

       本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/21328203,转载请注明。

以上是关于Why hashcode 31?的主要内容,如果未能解决你的问题,请参考以下文章

String hashCode 方法为什么选择数字31作为乘子

JDK1.8源码学习-String-hashCode方法为什么选择数字31作为乘子

快来,我悄悄的给你说几个HashCode的破事。

为啥 Java 的 String 中的 hashCode() 使用 31 作为乘数?

String.hashCode()为什么使用31作为乘数深度长文

为什么 String hashCode 方法选择数字31作为乘子