容器与并发容器

HashMap

hashmap:1.7的一个存储结构是,entry数组,加链表。
put:是通过计算出一个hash值,然后在通过这个hash值取模运算得到一个,下标值,这个时候相同的key或者不同的key计算出来的,下标是有可能相同的,当相同的时候,就出现了hash碰撞,在下标的下面衍生一个链表去存储。

get:是通过key值计算出一个,hash值,在通hash值取模得到一个下标值,去获取元素。

resize:扩容有两个条件,所占空间大于等于阈值百分之七十五并且当前添加的数据时entry头不为空也就是发生了hash冲突时开始扩容,扩容是在原来的一个大小基础上进行两倍扩容,然后将原来的数据全部进行一个hash,在取模放入entry中。

hashmap:1.8的一个存储结构是,node数组,加链表,加红黑树。

put:是通过计算出一个hash值,然后在通过这个hash值取模运算得到一个,下标值,这个时候相同的key或者不同的key计算出来的,下标是有可能相同的,当相同的时候,就出现了hash碰撞,在下标的下面衍生一个链表去存储,当链表过长使用了,红黑树转换

resize:扩容有两个条件,所占空间大于等于阈值百分之七十五开始扩容,扩容是在原来的一个大小基础上进行两倍扩容,然后将原来的数据全部进行一个hash,在取模放入node中。

1.8与1.7的主要区别在于存储结构的改变,将entry数据变成了一个node数组,然后再hash碰撞发生链表过长采用了红黑树进行了一个转换,同时扩容条件从两个变成了一个

ConcurrentHashMap

ConcurrentHashMap1.7:
存储结构:segment,segment中放数组与链表,先简单介绍一个segment是什么哈,这个东西是一个特殊的Hashtable因此这个东西他是线程安全的,然后对他里面的元素操作也就是安全的了,这个segment时根据初始容量来的,他不会进行扩容,这个值多大他就有多大的并发量。 

put:他先是通过key计算一个segment的一个下标位置,然后再计算一次数组的下标位置,然后放入进去,第一次是按&计算,第二次是按左移的方式计算。当计算出来了一个同样的下标时,就会hash碰撞,也是会有一个链表接收他,

get:先根据key计算出一个segment的位置然后,在计算数组的位置,然后就去获得元素

resize:在触发扩容的时候,外部的操作不能去操作这样的一个segment,然后去对entry数组扩容成原来的两倍,所有key值重新计算下标

1.8:存储结构变成了加node数组,加链表与红黑树,他去掉了分段锁的实现,采用了CAS机制去控制线程安全。

ArrayList

ArrayList :数据结构:名叫elementData的Object数组,他的一个默认长度为0,第一次add的时候,他会判断你是不是默认长度,是就设置为10,然后一直添加,直到size+1小于当前存储元素的大小,触发扩容, 扩容:先得到当前数组长度,然后在当前长度基础上扩容1.5倍,在通过一个elementData = Arrays.copyOf(elementData,新数组长度)这句代码在原有数组基础上,扩容大小,在赋值给这个elementData

CopyOnWriteArrayList :  CopyOnWriteArrayList 它是ArrayList对应的线程安全的并发容器,他的一个实现是,在写入copy一份新的数组给你去修改,并且对这个修改加了一个可重入锁保证只有一个线程能对他操作,在修改完成之后会把之前的引用指向现在的新数组,他的一个扩容机制是,每次add的时候size加1,所以这个add与get不是实时的,get操作是没有加锁的,这个list适用于读极多改极少的一个情况下使用

HashSet

HashSet:的数据结构就是一个HashMap,他已HashMap的key值不重复的特性,作为自己的一个value,

CopyOnWriteHashSet:的数据结构是一个,CopyOnWriteArrayList,他的一个,add方法使用了,CopyOnWriteArrayList中的一个addIfAbsent保证了数据不重复,这个方法的一个作用就是,判断你是否已经有了这个数据,有就不添加了,他同样也会有CopyOnWriteArrayList的一些特性,比如需要复制两份数据和,数据不是实时的

Queue

Queue队列,API分阻塞和非阻塞的,蓝色区域为阻塞队列独有方法

ArrayBlockingQueue : 是一个阻塞队列,他的数据结构是一个名叫 items 的Object类型数组。

他是怎么实现通过数组实现阻塞队列的呢,首先他会让你在初始化的时候让你在构造函数传一个参数,这个参数代表着队列的长度,

offer:offer方法的时候他会,先判断你是否为空,为空报错,然后在加一个可重入锁,然后判断目前当前是否有空间,没有空间直接返回false,有空间添加进去,然后返回true,在释放锁

put:put方法的时候他会,先判断你是否为空,为空报错,然后在加一个可重入锁,然后判断目前当前是否有空间,没有空间调用就休眠等待,有空间就去添加,最后释放锁

他们里面有个enqueue方法,这个方法是,用与添加  和  唤醒task 因为没有没有数据删除而休眠的线程

poll:看队列是否有数据,没数据返回空,有数据删除

task:判断是否有数据删除,有就删除,没就休眠,然后等待,

dequeue : 用与删除  和  唤醒put 因为空间满了而进入休眠的线程

他添加和删除,都是有顺序的,有个putIndex 代表 当前添加到了,下标几,然后take代表当然删除到了下标几。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值