资源描述:
《Hash底层实现原理》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、HashMap的底层实现原理一、HashMap的数据结构总述:哈希的出现时因为传统数据结构如线性表(数组,链表等),树中,关键字与其它的存放位置不存在对应的关系。因此在查找关键字的时候需要逐个比对,虽然出现了二分查找等各种提高效率的的查找算法。但是这些并不足够,希望在查询关键字的时候不经过任何比较,一次存取便能得到所查记录。因此,我们必须在关键字和其对应的存储位置间建立对应的关系f。这种对应的关系f被称为哈希函数,按此思想建立的表为哈希表。关键在于哈希函数如何构造。意思就是:关键字的存储位置是有关键字的内容决定的。数据结构
2、中有数组和链表来实现对数据的存储,但这两者基本上是两个极端。数组:数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难;链表:链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。哈希表:那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表。哈希表((Hashtable)既满足了数据的查找方便,同时不占用太多的内容
3、空间,使用也十分方便。哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法—— 拉链法,我们可以理解为“链表的数组”一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)&len-1获得,也就是元素的key的哈希值对数组长度取模得到。HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。这可能让我们很不解,一个线性的数组怎么实现按键值对来存取数据呢?这里HashMap有做一些处理。首先HashMa
4、p里面实现一个静态内部类Entry,其重要的属性有 key,value,next,从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。TransientEntry[]table;二、HashMap的存取实现://存储时:inthash=key.hashCode();//这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值
5、intindex=hash%Entry[].length;Entry[index]=value;//取值时:inthash=key.hashCode();intindex=hash%Entry[].length;returnEntry[index];(1)Put疑问:如果两个key通过hash%Entry[].length得到的index相同,会不会有覆盖的危险?这里HashMap里面用到链式数据结构的一个概念。上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry。打个比方,第一个键值对A进来,通过
6、计算其key的hash得到的index=0,记做:Entry[0]=A。一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?HashMap会这样做:B.next=A,Entry[0]=B,如果又进来C,index也等于0,那么C.next=B,Entry[0]=C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。也就是说数组中存储的是最后插入的元素。到这里为止,HashMap的大致实现,我们应该已经清楚了。publicVput(Kkey,
7、Vvalue){if(key==null)returnputForNullKey(value);//null总是放在数组的第一个链表中inthash=hash(key.hashCode());inti=indexFor(hash,table.length);//遍历链表for(Entrye=table[i];e!=null;e=e.next){Objectk;//如果key在链表中已存在,则替换为新valueif(e.hash==hash&&((k=e.key)==key
8、
9、key.equals(k))){Vol
10、dValue=e.value;e.value=value;e.recordAccess(this);returnoldValue;}}modCount++;addEntry(hash,key,value,i);returnnull;}voidaddEntry(inthash,Kkey,Vvalue,in