hashmap的几种类型

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、HashMap

hashmap是一种存储和检索键值对的数据结构,键具有唯一性,根据键计算得到的哈希值决定存放的位置,如果此位置为空,则直接将节点插入;如果不为空,则遍历链表看有没有相同的键值,如果有,则将当前值替换掉旧值,如果没有,则放在链表的最末端。

底层结构

数组加链表,链表是采用拉链法解决hash冲突的方式,当这个链表长度超过8以后,链表会转化为红黑树,以提高查询效率。

扩容机制

初始容量为16
当元素数量超过容量乘负载因子(0.75)时,就会将容量扩大至原来的两倍。
扩容后,会将所含元素重新hash一遍放入正确的位置,比较耗时。

二、LinkedHashMap

与HashMap的底层结构相比,加了一个双向链表用来维护HashMap的插入顺序。当我们需要按照插入顺序获取元素时,就使用linkedhashmap。

三、TreeMap

底层结构为红黑树,可以按照存入元素的key值对元素进行排序存储,默认按升序存储。

四、为什么重写equals方法需要重写hash方法

不重写的时候,equals方法是用来比较对象地址值是否相等。
重写是为了让equals可以比较对象具体的值是否相等。
默认的hashcode是计算对象内存地址的hash值。
如果只写了equals方法,就会出现两个对象equals结果相等,但hashcode值不相等的情况,在类似于hashmap这样的散列结构中就会出现问题。
因为hashmap使用hashcode来计算对象的位置,如果存储两个完全相同的对象,但有着不同的hashcode值就会导致两个对象就会存储在不一样的位置,违背了hashcode键值的唯一性。

五、linkedhashmap和treemap有什么不同

1、linkedhashmap底层结构是在hashmap的接触上加上一个双向链表,用来维护元素插入的顺序,可以按照插入顺序进行遍历;treemap底层是一个红黑树,按照键值对元素进行排序。
2、linkedhashmap在查找、新增、修改等方面的性能比较好;而hashmap在根据key值进行范围查询有比较好的性能。

六、hashtable和hashmap的区别

1、hashtable是线程安全的,hashmap是线程不安全的。
2、hashmap可以有一个空键值、多个空值;但hashtable不允许插入空键或控制。
3、单线程下更推荐hashmap,因为hashtable有锁的开销。

七、ConcurrentHashMap

推荐使用ConcurrentHashMap保证线程安全。

为什么ConcurrentHashMap的键和值都不能为空

因为多线程并发环境下无法保证get(key)得到null的结果是设置的还是key值没有对应的映射,因为hashmap单线程下可以通过containskey来判断,但ConcurrentHashMap在使用containskey的同时,可能值已经被其他线程改变了。

jdk1.7实现方式

通过分段锁实现线程安全的,将数组分成多段 segement,通过继承ReentrantLock对每个segment进行上锁。这样当多线程同时想要修改同一个segment中的数据时,只允许一个线程进行修改。(对写加锁)但是 ConcurrentHashMap 不支持将冲突的链表转换为红黑树,因为在多线程并发修改链表时,会导致死锁和数据不一致等问题。

jdk1.8实现方式

底层结构和hashmap一样变成了数组加链表/红黑树的结构,但取消了分段锁,而是使用了更细粒度的锁。采用CAS+Sychronized实现了桶级别的锁,只需要锁住每个链表的首节点或是红黑树的根节点就行,这样多线程只有在同时访问一个桶时才会出现冲突。
在添加元素的时候会判断容器是否为空,如果为空,则会用CAS和volatile初始化;
如果不为空,根据存储的元素计算该位置是否为空,如果该位置为空,就会用CAS来设计该节点,;否则使用sychronized加锁去实现,去遍历桶中的元素,替换或新增节点到桶中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值