最近看HashMap的源码,相同的下标容易出现hash冲突,但是调试需要hash冲突。本文模拟哈希冲突。Hash冲突原理HashMap冲突是key先调用hash()方法:staticfinalinthash(Objectkey){inth;返回(键==空)?0:(h=key.hashCode())^(h>>>16);}然后用hash值和tab数组的长度做AND运算:(n-1)&计算出的下标如果它们一致,hash将导致冲突。通过ASKII码获取单个字符开始想到的是单个字符,比如a、b、c、d、e等字符,但是一一尝试会很繁琐。我想到了ASKII码:从1到100遍历ASKII码。通过ASKII码获取单个字符:for(inti=33;i<100;i++){charch=(char)i;Stringstr=String.valueOf(ch);}通过str获取下标,HashMap默认长度为16,所以n-1为15:intindex=15&hash(str);获取哈希冲突的字符并计算相同的索引,然后将它们放入列表中。HashMap中放置了不同的索引,完整代码如下:Map>param=newHashMap<>();对于(inti=33;i<100;i++){charch=(char)i;字符串str=String.valueOf(ch);intindex=15&hash(str);Listlist=param.get(index);if(list==null){list=newArrayList<>();}list.add(str);param.put(索引,列表);}param.forEach((k,v)->System.out.println(k+""+Arrays.toString(v.toArray())));输出:0[0,@,P,`]1[!,1,A,Q,a]2[",2,B,R,b]3[#,3,C,S,c]4[$,4,D,T]5[%,5,E,U]6[&,6,F,V]7[',7,G,W]8[(,8,H,X]9[),9,I,Y]源码调试根据上面的计算结果,使用其中一个例子:1[!,1,A,Q,a]首先添加数据:Mapmap=newHashMap<>();map.put("!",1);map.put("1",1);map.put("A",1);先添加1,A,Q三个数据。再添加问。打开调式,定位到putVal方法:finalVputVal(inthash,Kkey,Vvalue,booleanonlyIfAbsent,booleanevict){Node[]tab;节点p;诠释n,我;如果((tab=table)==null||(n=tab.length)==0)n=(tab=resize()).length;如果((p=tab[i=(n-1)&hash])==null)tab[i]=newNode(hash,key,value,null);else{节点e;Kk;if(p.hash==hash&&((k=p.key)==key||(key!=null&&key.equals(k))))e=p;elseif(pinstanceofTreeNode)e=((TreeNode)p).putTreeVal(this,tab,hash,key,value);else{for(intbinCount=0;;++binCount){if((e=p.next)==null){p.next=newNode(hash,key,value,null);if(binCount>=TREEIFY_THRESHOLD-1)//-1对于第一个treeifyBin(tab,hash);b雷克;}if(e.hash==hash&&((k=e.key)==key||(key!=null&&key.equals(k))))中断;p=e;}}if(e!=null){//键VoldValue=e.value的现有映射;如果(!onlyIfAbsent||oldValue==null)e.value=value;节点访问后(e);返回旧值;}}++模数;如果(++大小>阈值)调整大小();节点插入后(逐出);returnnull;}在源码分析一文HashMap源码分析详解(下)中,我们知道在上面代码的第16行会发生hash冲突,一直是for循环遍历链表,替换相同的key或向链表添加数据:for(intbinCount=0;;++binCount){if((e=p.next)==null){p.next=newNode(hash,key,value,null);if(binCount>=TREEIFY_THRESHOLD-1)//-1对于第一个treeifyBin(tab,hash);休息;}if(e.hash==hash&&((k=e.key)==key||(key!=null&&key.equals(k))))休息;p=e;}方式:会遍历for循环,直到p.next==null遍历到链尾,然后在链表尾添加节点数据:p.next=newNode(hash,key,值,空);通过(h=key.hashCode())^(h>>>16)高位运算哈希码和(n-1)&哈希表数组长度求模,分析哈希冲突原理,通过ASKII获取字符串代码遍历,获取hash冲突的字符。调用put方法调用hash冲突源码。