当前位置: 首页 > 科技观察

JavaHashMap核心源码解读

时间:2023-03-20 13:52:37 科技观察

本文简单分析一下HashMap实现的源码。使用的HashMap源代码的版本信息如下:/**@(#)HashMap.java1.7307/03/13**Copyright2006SunMicrosystems,Inc.保留所有权利。*SUNPROPRIETARY/CONFIDENTIAL。使用受许可条款约束。*/1。概述Java中的每个对象都有一个哈希码,可以通过hashCode()方法获得。hashCode()的取值与对象的equals方法息息相关,是判断两个对象的值是否相等的依据,所以我们在重写一个类的equals方法的时候,也必须重写hashCode方法。例如String的hashCode方法为:publicinthashCode(){inth=hash;if(h==0){intoff=offset;charval[]=value;intlen=count;for(inti=0;ie=table[i];e!=null;e=e.next){对象k;if(e.hash==hash&&((k=e.key)==key||key.equals(k))){VoldValue=e.value;e.value=值;e.recordAccess(这个);返回旧值;}}modCount++;addEntry(散列,键,值,我);返回空值;在HashMap中,我们的key可以为null,所以第一步处理key为null的情况。当key不为null的时候,你可能会想:嗯,除以表长取模就行了,但是这里没有,不过好像又做了一次hash,这是为什么呢?这个得先看看indexFor(hash,table.length)这个方法。这个方法是一个staticintindexFor(inth,intlength){returnh&(length-1);}确定存储位置。因为HashMap中表的长度是2n(我们考虑的都是二进制操作),所以h&(length-1)等价于h%length,也就是说如果不对原来的hashCode进行变换的话,在这种情况下,去掉lowlength-1位后的部分不会对key在表中的位置有任何影响,所以只要lowlength-1位不变,不管高位都会有冲突,所以找到一种使高位匹配其结果的方法也有影响,所以我对hashCode进行了另一个哈希staticinthash(inth){//此函数确保hashCodes仅相差//每个位的常数倍数position有一个有限的//碰撞次数(在默认负载因子下大约为8)。h^=(h>>>20)^(h>>>12);返回h^(h>>>7)^(h>>>4);}当found找到key对应的位置时,遍历对应位置Entry的链表,如果key存在则更新对应的value,返回旧值。如果是新密钥,请添加它。modCount用于记录hashmap结构变化的次数,这是hashmap的fail-fast机制所需要的(当一个线程获得了map的cursor,另一个线程修改了map的结构,然后原准备遍历线程会抛出异常)。addEntry的方法如下voidaddEntry(inthash,Kkey,Vvalue,intbucketIndex){Entrye=table[bucketIndex];table[bucketIndex]=newEntry(hash,key,value,e);如果(大小++>=阈值)调整大小(2*table.length);}get方法publicVget(Objectkey){if(key==null)returngetForNullKey();inthash=hash(key.hashCode());for(Entrye=table[indexFor(hash,table.length)];e!=null;e=e.next){对象k;if(e.hash==hash&&((k=e.key)==key||key.equals(k)))返回e.value;}返回空值;}get方法是和putposition一样计算key在表中的位置,然后遍历该位置的链表,找到hash值和key相等的Entry,返回值。