现象:
计费和账户的交互通过Map来交互,基本数据格式如下{"pp900_88",20,"pp900_61",2……}
在不同的取值情况下,较多数据返回了相同的价格结果,导致计算价格错误。
应用场景:
产品计算价格时,使用cache缓存了价格结果数据,cache的key值是传入map的hashCode,本意是要实现完全相同的Map传入值从缓存取数据,减少数据库的访问。
原因分析:
一。通过如下代码模拟线上应用:
- public static void main(String[] args) {
- HashMap map = new HashMap();
- for(int i = 0 ; i < 100 ; i ++){
- HashMap m1 = new HashMap();
- m1.put("pp900_88", i);
- m1.put("pp900_59", 30);
- m1.put("pp900_62", 6);
- m1.put("pp900_63", 4);
- m1.put("pp900_60", "y");
- m1.put("pp900_61", i);
- int hs = m1.hashCode();
- map.put(hs, map.get(hs)+","+i);
- // System.out.println(i+"==="+m1.hashCode());
- }
- System.out.println(map.size());
- System.out.println(map);
- }
结果如下:
- {-479160017=null,56,57,58,59,60,61,62,63,
- -479160049=null,40,41,42,43,44,45,46,47,
- -479160033=null,48,49,50,51,52,53,54,55,
- -479160129=null,0,1,2,3,4,5,6,7,64,65,66,67,68,69,70,71,
- -479160097=null,16,17,18,19,20,21,22,23,80,81,82,83,84,85,86,87,
- -479160113=null,8,9,10,11,12,13,14,15,72,73,74,75,76,77,78,79,
- -479160065=null,32,33,34,35,36,37,38,39,96,97,98,99,
- -479160081=null,24,25,26,27,28,29,30,31,88,89,90,91,92,93,94,95}
可以看到,重复是很有规律的,连续7、8个数据都是重复的,当然在真实情况下重复概率不会这么高(因为Map的其他key-value值不太可能完全相同)
二。分析hashCode的产生
HashMap的hashCode根据key和value值来计算hashCode,最后将各个元素的hashCode值相加,即
- public final int hashCode() {
- return (key==null ? 0 : key.hashCode()) ^
- (value==null ? 0 : value.hashCode());
- }
以 m1.put("pp900_88", 1); m1.put("pp900_61", 1);和
m1.put("pp900_88", 2); m1.put("pp900_61", 2);为例子:得到的key-Value的hashCode值如下
key key的hashCode value的hashCode Map的hashCode(key^value)
pp900_88 -79859962 1 -79859961