2021-01-15

HashMap底层原理

在jdk1.8之前,底层是通过数组+链表实现的,当我们创建hashmap时会先创建一个数组。

当我们用put方法存数据时,先根据key的hashcode值计算出hash值,然后用这个哈希值确定在数组中的位置,再把value值放进去,如果这个位置本来没放东西,就会直接放进去;如果之前就有,就会生成一个链表,把新放入的值放在头部。

当用get方法取值时,会先根据key的hashcode值计算出hash值,确定位置,再根据equals方法从该位置上的链表中取出该value值。

当容量超过当前容量的0.75倍之后,就会自动扩容为原来容量的2倍。这个0.75就是负载因子。

但是在jdk1.8之后,最大的不同就是其由 数组+链表+ 红黑树组成。因为在1.7的时候,这个链表的长度不固定,所以如果key的hashcode重复之后,那么对应的链表的数据的长度就无法控制了,get数据的时间复杂度就取决于链表的长度了,为了提高这一部分的性能,加入了红黑树,如果链表的长度超过8位之后,会将链表转换为红黑树,极大的降低了时间复杂度

HashMap 线程不安全,有多个线程同时 HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以使用 ConcurrentHashMap。

介绍下ConcurrentHashMap

ConcurrentHashMap是线程安全的HashMap,内部采用了的"分段锁"策略,它的主干是个Segment数组,通过继承ReentrantLock 来进行加锁。所以每次锁住的是一个 segment,这样只要保证每个 Segment 是线程安全的,也就实现了全局的线程安全。一个Segment就是一个子哈希表,默认有16 个 Segment。所以理论上,只要它们的操作分别分布在不同的 Segment 上,最多可以同时支持 16 个线程并发写。

创建线程的方式

1.继承Thread类,或者直接实现Runnable接口,然后再重写下run方法就行了。启动线程的方式就是调用类里边的 start方法。

2.实现 Callable 接口,他的执行代码的方法是call方法,可以有返回值

3.通过线程池来实现,线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可。节省了开辟子线程的时间,提高代码执行效率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值