Java 深入理解hashcode()方法——Boolean
环境:jdk1.8
public static void main(String []args)
{
Boolean b2=true;
Boolean b3=false;
System.out.println("ture的hash值:"+b2.hashCode());
System.out.println("false的hash值:"+b3.hashCode());
}
输出结果:
ture的hash值:1231
false的hash值:1237
为什么会返回1231与1237这两个诡异的数字呢(虽然hashcode值一直都很诡异@_@)?
让我们打开Boolean的源码
/** * Returns a hash code for a {@code boolean} value; compatible with * {@code Boolean.hashCode()}. * * @param value the value to hash * @return a hash code value for a {@code boolean} value. * @since 1.8 */
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
为什么是1231和1237,而不是我们经常用的1和0?
然后查阅了资料,发现有一种解释如下:
不管使用什么哈希算法,其哈希函数都要极可能避免冲突。简单地说,不同的值要落在不同的存贮单元。认真观察,很容易发现1231和1237都是素数。使用素数的好处在于,对于不同数目的存贮单元m,1231和1237基本上都与其互质,除非m等于或数倍于1231和1237。这种情况下,true和false也能落到不同的单元去。
其实这也就是一般hash算法取值的默认规则,取素数。
一般来说,单个Boolean类型是没有求hashcode的需求的。
比如这样:
public static void main(String []args)
{
HashMap<Boolean,String> map=new HashMap<Boolean, String>();
map.put(true,"这是true");
map.put(false,"这是false");
}
此时的Boolean的hashcode规则怎么去取都是无所谓的,取0,1可以,取1231,1237也可以,因为key有且最多只有2种可能,所以必然不可能发生碰撞。
但是,Boolean的hashcode一般是作为整体的一部分而存在的,此时就需要考虑碰撞冲突问题了。
比如下列代码
class hashTest
{
Boolean a;
Boolean b;
Boolean c;
Boolean d;
/** * 重写hashcode * @return */
@Override
public int hashCode()
{
int hashResult=0;
hashResult = 31 * hashResult + a.hashCode();
hashResult = 31 * hashResult + b.hashCode();
hashResult = 31 * hashResult + c.hashCode();
hashResult = 31 * hashResult + d.hashCode();
return hashResult;
}
}
很显然,当Boolean的hashcode默认取0,1时。。。。麻烦就大了,几乎每次都会发生碰撞。
而取1231,1237,对于不同数目的存贮单元m,1231和1237基本上都与其互质,除非m等于或数倍于1231和1237。所以发生碰撞的概率大大减小。
所以,Boolean的hashcode()采用了1231,1237两个素数,而不是其他,比如0,1.
而至于为啥不是其他素数,那估计Java源代码作者比较喜欢1231,1237,想留个彩蛋?