学习笔记2 Haspmap简述

   HashMap基于Map接口实现,数据元素以key-value的形式存在,是由数组加链表组合实现,原理图网上太多,大同小异,就不贴了。

   默认初始容量为16,加认装载因子为0.75。同时,Hashmap提供了三种构造方法,借助这些构造方法也可以自己设置初始容量和装载因子(public HashMap(int initialCapacity, float loadFactor))。

   加载因子0.75指当HashMap中的元素数量达到容量的75%时,需要进行扩容,每次扩容后,容量必须为2的N次方。原因:加载因子过大,如设成0.99,会导致存数据是冲突率极高,不停地在链表上加元素,

读取元素时开销就会很大,加载因子过小,如0.5,虽然冲突率较低,查找速度快,但会导致极大地空间浪费,所以0.75算是个折衷方案,平衡了空间利用率和冲突几率。

   每次扩容后容量必须为2的N次方,原因:这个与HashMap中计算下标的算法有关

 static int indexFor(int h, int length) {
        return h & (length-1);
    }

里边的h是元素的hash码,这行代码的作用是对hash码按HashMap的容量取余,得到的值为HashMap的下标。原因在于这个length-1。如16-1转换成2进制是1111,32-1转换成2进制是11111,所以,容量为2的N次方就是要保证length-1后得到的2进制数末几位全为1。如果不全为1会有什么后果呢?以15为例,15-1转换成2进制是1110,因为代码中做得是按位与运算,  因为末置位为0,不管h的末置位是几&0得到的结果都是0,也就是说末置位为1几种可能是永远得不到。例如1111,1011等,这样就造成了一部分的空间浪费。

HashMap的线程不安全:两个输入元素的key值相同时,会将后存入的元素存到数组中,先进入的元素会添加到链表中,由后存入元素的next属性指向。多线程的时候,如果两个线程同时往HashMap中存元素,恰好两个线程的存的元素的key值相同,而且这两个线程恰好同时取到了对应key的头结点,那么一定会有一个元素丢失,这就是HashMap的线程不安全问题。相对的HashTable是线程安全的,通过每个方法加了sychronized实现,所以效率低下。

JDK中对HashMap的线程不安全问题提供了两种解决方案:(1)通过Collections.synchronizedMap()返回一个新的Map,这个新的map就是线程安全的,注意返回的不是一个HashMap,是一个Map的实现。此方法封装了所有的线程不安全的HashMap方法,调用方法是对整个HashMap同步。(2)ConcurrentHashMap,ConcurrentHashMap采用的是分段锁机制,把Map分成N个Segment,多线程时只需要锁住Segment而不用锁整个Map,极大地提高了效率。其中放入哪个Segment也是通过Hash码计算的。

转载于:https://www.cnblogs.com/HC-blog/p/7384186.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值