最近有小伙伴在使用java1.6的jdk时,发现1.6版本switch..case不支持字符串类型。
首先,升级jdk版本是不可能的,比较老项目,只能用1.6的。
比如下面这样写,jdk1.6不支持。
于是有个小伙伴说,这样写不就可以了?
的确,这样写是可以的,但并不建议。
首先,需要理解一下hashCode方法的含义,以及知道不同String,调用hashCode方法返回的值可能是相同的,比如Aa和BB的hashCode方法返回的都是.这时如果用在这里,就有问题了。
我们再来看看String的hashCode方法源码:
1、为什么有个常数31作为生成hashCode算法的一部分?
大家都知道,计算机的乘法涉及到移位计算。当一个数乘以2时,就直接拿该数左移一位即可!选择31原因是因为31是一个质数!
所谓质数是指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。在存储数据计算hash地址的时候,我们希望尽量减少有同样的hash地址,所谓“冲突”。如果使用相同hash地址的数据过多,那么这些数据所组成的hash链就更长,从而降低了查询效率!
所以在选择系数的时候要选择尽量长(31=[2])的系数并且让乘法尽量不要溢出(如果选择大于的数,很容易溢出)的系数,因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。
31的乘法可以由i*31==(i5)-1来表示,现在很多虚拟机里面都有做相关优化,使用31的原因可能是为了更好的分配hash地址,并且31只占用5bits!在java乘法中如果数字相乘过大会导致溢出的问题,从而导致数据的丢失.而31则是素数(质数)而且不是很长的数字,最终它被选择为相乘的系数。
2、我们再来看看val[i]其实就是字符串里的字符,当与整数相加时,会转换成一个整数。
对于字符串Aa,hash=0+65+31*65+97=
对于字段串BB,hash=0+66+31*66+66=;
所以不同的字符有可能生成相同的hashCode,在swicht..case里使用hashCode的写法,是不建议的。
当然,当字符比较长时,冲突的概率是比较低的。