学习笔记——HashMap的底层结构及相关知识

HashMap底层是由数组和链表组成的,它的原理是根据keyhashcode再散列取其hash值,然后通过这个hash值与table长度得到key对应的value应该存在数组的哪个位置,其结构如下图



我们在看下HashMap实现putget的代码以及新建一个HashMap的代码

HashMap有几个默认参数,DEFAULT_INITIAL_CAPACITY是默认初始容量,值为16MAXIMUM_CAPACITY为最大容量,值为2^30

DEFAULT_LOAD_FACTOR为默认加载因子,值为0.75

HashMap主要的几个成员变量有数组table,大小size,加载因子loadFactor,操作次数modCount,大小临界值threshold

通常我们新建一个HashMap都是用的new HashMap()这个构造方法,那我们就看一下在HashMap里面具体是怎么初始化的

public HashMap() {

   this.loadFactor = DEFAULT_LOAD_FACTOR;//取默认加载因子作为新建的HashMap的加载因子

        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);//默认初始容量乘以加载因子得出临界值

        table = new Entry[DEFAULT_INITIAL_CAPACITY];//新建一个长度为16的数组

        init();//源代码中该方法无具体实现

    }

下面我们看一下我们常用的putkeyvalue)方法的实现(自己写的,整体思路和源代码一致,可能会有一些小的问题)

public  V put(K key,V value){

if(key==null){

return putvaluefornul(value);//HashMap中,put的时候,如果key是null,一定是存放在table[0]所在的链表中

}

int hash = hash(key.hashcode());//对key的hashcode再散列,得到在数组中坐标对应的hash

int i = indexFor(hash,table.length);//根据key得到的hash和数组长度得到该key对应的数组下标

for(Entry e = table[i];e!=null;e = e.next){

if((e.hash==hash)&&(e.key==key||e.key.equals(key))){//根据hash和key比较看该key是否已存在

Object old = e.value;

e.value = value;//如果该key存在,则替换value

return old;

}

}

addEntry(hash,key,value,i);//不存在的时候增加

return null;

}

 

public V putvaluefornul(V value){

for(Entry e = table[0];e!=null;e=e.next){

if(e.key==null){

Object old = e.value;

e.value = value;//如果该key存在,则替换value

return old;

}

}

addEntry(0,null,value,0);//不存在的时候增加

return null;

}

 

public addEntry(int hash,K key, V value, int index){

Entry e = table[index];

e = new Entry(hash,key,value,e);//Entry的构造方法(int hash,K key,V value,Entry next)

if(size++>=threshold){

.....//这一块是扩大数组容量,通常是扩大0.5倍加1,扩容并不是单纯的扩大数组长度,元素的位置也都变了

}

}


我们再看一下get方法的实现

public V get(K key){

if(key==null){

return getvaluefornull(key);//如果key是null,则去table[0]中查找

}

int hash = hash(key.hashcode());//对key的hashcode再散列,得到在数组中坐标对应的hash

int i = indexFor(hash,table.length);//根据key得到的hash和数组长度得到该key对应的数组下标

for(Entry e = table[i];e!=null;e = e.next){

if((e.hash==hash)&&(e.key==key||e.key.equals(key))){//根据hash和key来查找value

return e.value;

}

}

return null;

}

 

public V getvaluefornull(K key){

for(Entry e = table[0];e!=null;e = e.next){

if(e.key==null){

return e.value;//根据key来查找对应的value

}

}

return null;

}

因为HashMap不是线程安全的,所以其中有modCount这个字段,可以用计HashMap被修改的次数来判断有几个线程修改了它。

 

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值