hashMap

1. hashMap内部实现

HashMap是基于哈希表的 Map 接口的实现

HashMap就是以散列表的形式将数据存储到hashTable里面去。

hashTable的数据结构:数组+链表的形式 ,同一下标如果有多个值,则用链表连起来。

假设只放2个值(数据量),则需要定义hashMap容量(N)为:N>=2*1.34 &&N==2的K次方(K=1,2,3...)

这里N=4 (N一定要设为2的k次方,一是确保容量足够,2是为了让hash值均匀分布在表(数组)中,否则有可能会导致不同key的值进入到相同的插槽,形成链表,性能急剧下降,所以一定要保证下面(a%b == (b-1)&a (与运算))&前面部分中的二进制位全为1,才能最大限度的利用hashCode,以生产更多的散列结果)

Map<string,string> map=new HashMap<>(4);

map.put("name","zhangsan");

map.put("sex","male");

2.生成hashCode

@Override

public int hashCode(){

return Objects.hash("name")//or "sex"

}

4.为什么使用hashCode?

hashMap速度快,是因为他使用散列表

散列表是根据key的hashcode值生成数组下标(通过内存地址直接查找,无任何判断,速度快)

生成hashcode的过程就是将key转为一个唯一的整型的数的过程

将string类型的key转为hashCode

转化方法:

public int hashCode(){

int hash=0;

int h=hash;

if(h==0&& value.length>0){

char val[] =value;

for(int i=0;i<value.length;i++){

h=31*h +val[i];

}

hash=h;

 }

return h;

}

例如:value(key)是字符串 "abc"  ('a'的ascii码是97)

则 在for循环内:第一次结果 h=97;第二次 h=31*97+98;第3次 h=31*(31*97+98)+99

最终返回第3次h的值 为hashCode

取31的目的:尽可能使各个key的hashCode不同,不同key的hashcode是有可能相同的。

打个比方:先按照hashcode分配不同的猪圈,将hashcode相同的猪放到一个猪圈里。 
查找的时候,先找到hashcode对应的猪圈,然后在逐个比较里面的小猪。 

所以问题的关键就是建造多少个猪圈比较合适。 
如果每个小猪的体重全部不同(考虑到毫克级别),每个都建一个猪圈,那么我们可以最快速度的找到这头猪。缺点就是,建造那么多猪圈的费用有点太高了。

 

3. 通过生成的hashCode 按一定规则将key对应的值放入hashTable中

hashTable 是以数组的形式存储值的

val result=hash(key)

static final int hash(Object Key){

int h;

return (key==null)?0:(h=key.hashCode())^(h>>>16);} 

右移16位的目的增大空间,以避免在使用get方法时候 不同hashcode跟数组长度-1进行与运算时 取到同一个位置的值,造成错误。也就是说虽然两个key的hashcode不同,但经过与运算也可能有相同的hash值。

实际存储值的地方=arr[result],由Put方法将值存到下标对应的内存区域中。

 

4.调用get方法时候:比较表中已有的hash与传入参数key生成的hash是否相等时:

为什么不用a%b 而用 (b-1)&a ? :对于现代处理器,除法和求余数是最慢的动作。

当 b是2的指数时,a%b == (b-1)&a (与运算)

5. 不同的key可能有相同的hashcode(少量,可以调整),但不同的hashcode其对应的hash()返回值一定不同。 

 

6.如何线程安全的使用HashMap

http://www.importnew.com/21396.html

对于线程不安全的类,是不能采用单例对象以减少对象的生成个数的,需要把线程不安全的类放到方法体中,生成相关的对象。

对于线程不安全的类的对象,同一个对象只能被1个线程使用1次,不能被复用,否则会出一些莫名其妙的未知错误。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值