什么是Hash冲突? 对于混列冲突,必须提到混列映射的存储实现
如下图所示
也就是说,图中重复颜色的要素发生碰撞的就是Hash碰撞
计算得到的混列值相同,需要放入同一bucket时为混列冲突
解决Hash冲突(冲突)吗? java中使用的链接法、拉链法
jdk1.7中
调用HashMap的put或get方法时,首先调用hashcode方法以查找相关key,如果存在冲突,则调用equals方法
JDK1.7的时候使用Entry数组存储数据。 在key的hashcode中取模型,决定了key在数组中的位置。 如果hashcode相同,或者在hashcode中取模的结果相同,则这些key位于Entry数组的同一体量中。
jdk1.8中
只有在链表大于8、数组大于64时才进行转换,链表转换为红黑树,并调用treeifyBin函数
为什么8变成了红色的黑色的树? 根据概率学泊松分布
指示桶的链表元素超过8时,将自动转换为红黑树。 如果桶元素小于或等于6,则树结构将恢复为链表形式
中间有差7可以防止链表和树之间频繁切换
为什么不直接用红黑树? 因为红黑树需要左转、右转操作,不需要单链表。
主要考察链表与红黑树的比较:
1 )元素小于8个时,查询成本高,新增成本低
2 )元素大于8个时,查询成本低,追加成本高
1.7的put方法
publicvput(kkey,V V value ) if ) key==null ) returnputfornullkey ) value; inthash=hash(key.hashcode (); intI=indexfor(hash,table.length ); for(entryk,V e=table[i]; e!=null; e=e.next({objectk; if(e.hash==hash((k=e.key )|key.equals ) k ) ) { V oldValue=e.value; e .值=值; e .记录访问(this; 返回载荷值; } }模具计数; addentry(hash,key,value,I ); 返回空值; }/* * * addsanewentrywiththespecifiedkey, valueandhashcodeto * thespecifiedbucket.itistheresponsibilityofthis * methodtoresizethetableifappropriate.* * subclassoverridesthistoalterthebehaviorofputmethod.*/voidaddentry (int hash,K key,V value,int bucketIndex ) {EntryK,} if(size=threshold ) resize(2*table.Length ); } 1.8的put方法
publicvput(kkey,V value ) returnputval ) hash ) key,key,value,false,true ); }/* * * implements map.putandrelatedmethods.* * @ paramhashhhashforkey * @ paramkeythekey * @ paramvaluethevaluetoput * @ don ' tchangeexistingvalue * @ paramevictiffalse,thetableisincreationmode.* @ returnpreviousvalue ornullifnone */finalvpupure NodeK,V p; int n,I; if () tab=table )==null||(n=tab.Length )=0) n=(tab=resize ) ).length; if () p=tab(I=(n-1 ) hash]] ) null (tab ) I )=new node (hash,key,value,null ); else { NodeK,V e; k; if(p.hash==hash ) (k=p.key )==key||(key!=nullkey.equals(k ) ) (e=p; elseif(pinstanceoftreenode ) e=(treenodek,v ) 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=tree ify _ threshold-1 )/-1for1STTreeifybin(tab,hash ); 布雷克; (if ) e.hash==hash((k=e.key )==key||(key!=nullkey.equals(k ) ) (break; p=e; }if(e!=null (//existingmappingforkeyvoldvalue=e.value; if (! olyifabsent|||old value==null (e.value=value; afternodeaccess(e; 返回载荷值; } }模具计数; 大小阈值(if )大小); 自动识别(evict; 返回空值; }参照报道
3359 blog.csdn.net/lovezhaohaimig/article/details/86595113
总结网上说的话
jdk7数组单链表jdk8数组(单链表红黑树) ) ) ) ) ) )。
jdk7链表头插jdk8链表尾插
如果在头部插入: resize后插入传输数据,则无需遍历链表并将其插入末尾
头插:最近因put的可能性等被获取,头插遍历到链表的头时一致
在头部插入: resize后,链表可能会反转; 同时resize可能会产生循环链
jdk7先扩展,put jdk8先put,然后扩展(why? 有什么区别吗? )
jdk7计算混列运算多jdk8计算混列运算少
jdk7受rehash的影响,调整了jdk8后,变为(起始位置) or (起始位置旧容量)