周启著名的《Effective java》这本书里面,对为什么使用31进行hascode进行了说明:
之所以使用31,是因为他是一个奇素数。如果乘数是偶数的话,采用乘法,信息就会丢失,等价于与2相乘的左位移。31有一个很好的性能,就是可以使用位移和减法来替代乘法,可以得到更好的性能:31*i=(i<<5)-i,现代的vm可以自动的完成这种优化,这个公式可以很简单的推导出来的。
素数有一个很好的优点,就是使用一个数字来乘以这个素数,得出来的数只能被1,素数和这个数,整除,这个就是3n只能被3和n和1整除。这个优点可以用在hashmap里面的用来解决key的碰撞。
所以综上;
1,素数,相比较于偶数更具有优点
2,素数与其他数相乘,3n结果只能被3和n和1整除,可以减少hash冲突,更好的分配hash地址。
3, 31拥有性能的优势,相比较于乘,现在vm可以做到31*i=(i<<5)-i的优化,提高性能。
4,31只占用5bits!在java乘法中如果数字相乘过大会导致溢出的问题,从而导致数据的丢失,而31则是素数(质数)而且不是很长的数字,最终它被选择为相乘的系数的原因。
参考:https://blog.csdn.net/mxw2552261/article/details/91349677
网友评论