学会了CopyOnWriteArrayList可以再多和面试官对线三分钟

本文介绍了ArrayList与CopyOnWriteArrayList的区别及其在并发环境下的表现。ArrayList是非线程安全的,适合单线程环境,而CopyOnWriteArrayList是线程安全的,适用于读多写少的并发场景。CopyOnWriteArrayList通过复制数组实现并发修改,避免了并发修改异常,但每次修改都需要复制数组,可能导致内存占用增加。因此,需要根据具体应用场景选择合适的集合类型。
摘要由CSDN通过智能技术生成

ArrayList是大家用的再熟悉不过的集合了, 而此集合设计之初也是为了高效率, 并未考虑多线程场景下, 所以也就有了多线程下的CopyOnWriteArray List这一集合

回一下ArrayList

f ail- f ast 快速失败机制, 一个线程A在用迭代器遍历集合时, 另个线程B
这 时 对 集 合 修 改 会 导 致 A 快 速 失 败 , 抛 出 Co nc urre nt Mo d i f i c a t i o n E x c e p t i o n 异常。在java. util中的集合类都是快速失败的

f ail- safe 安全失败机制, 遍历时不在原集合上, 而是先复制一个集合, 在拷贝的集合上进行遍历。在java.util.concurrent包下的容器类是安全失败的, 建议在并发环境下使用这个包下的集合类

在这里插入图片描述

ArrayList定义:

public class ArrayList<E>  extends  AbstractList<E>
implements List<E>, RandomAccess, Cloneable,   java.io.Serializable     {
      }

ArrayList简介:

ArrayList是实现List接口的可变数组,并允许null在内的重复元素

底层数组实现,扩容时将老数组元素拷贝到新数组中,每次扩容是其容量的1.5 倍,操作代价高

采用了Fail-Fast机制,面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险

ArrayList是线程不安全的,所以在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList

重点关注问题:

Ar r ay Lis t的默认初始化大小是 10 ( 在新建的时候还是空, 只有当放入第一个元素的时候才会变成10 ) , 若知道Ar r ay Lis t的大致容量, 可以在初始化的时候指定大小, 可以在适当程度减少扩容的性能消耗( 看下一个问题解析) 。

至于为何是10

据说是因为s un的程序员对一系列广泛使用的程序代码进行了调研, 结果就是10 这个长度的数组是最常用的最有效率的。也有说就是随便起的一个数字, 8 个12 个都没什么区别, 只是因为10 这个数组比较的圆满而已。

ArrayList的扩容机制

当添加元素的时候数组是空的, 则直接给一个10 长度的数组。当需要长度的数组大于现在长度的数组的时候, 通过新= 旧+ 旧> > 1 ( 即新 = 1 . 5倍的旧) 来扩容, 当扩容的大小还是不够需要的长度的时候, 则将数组大小直接置为需要的长度( 这一点切记! ) 。

ArrayList 特点访问速度块, 为什么? 插入删除一定慢吗? 适合做队列吗?

Ar r ay Lis t从结构上来看属于数组, 也就是内存中的一块连续空间, 当我们get( index) 时, 可以直接根据数组的首地址和偏移量计算出我们想要元素的位置, 我们可以直接访问该地址的元素, 所以查询速度是O ( 1 ) 级别的。

我们平时会说Ar r ayList 插入删除这种操作慢, 查询速度快, 其实也不是绝对的。

当数组很大时, 插入删除的位置决定速度的快慢, 假设数组当前大小是一千万, 我们在数组的index 为0 的位置插入或者删除一个元素, 需要移动后面所有的元素, 消耗是很大的。但是如果在数组末端index操作, 这样只会移动少量元素, 速度还是挺快的( 插入时如果在加上数组扩容, 会更消耗内
存) 。

个人觉得不太适合做队列, 基于上面的分析, 队列会涉及到大量的增加和删除( 也就是移位操作) , 在Ar r ay Lis t中效率还是不高。

ArrayList 底层实现就是数组, 访问速度本身就很快, 为何还要实现 RandomAccess ?

R andom Ac c es s 是一个空的接口, 空接口一般只是作为一个 标识, 如S er ializ able接口.。

JD K 文档说明R andom Ac c es s 是一个标记接口( Mar ker inter fac e) , 被用于Lis t接口的实现类, 表明这个实现类支持快速随机访问功能( 如Ar r ay Lis t ) . 当程序在遍历这中Lis t的实现类时, 可以根据这个标识来选择更高效的遍历方式。

在这里插入图片描述

优缺点

上面说的查询速度快自然就是其中的优点, 除此之外, 还可以存储相同的元素

底层数据结构属于数组, 和数组的优缺点大同小异, 数组属于线性表, 更适合于那种在末尾经常添加数据的场景, 而对于在整个l i s t 中各个位置随机添加元素比较多的情况则不太合适

因为可能会涉及到很多元素位置的移动

A r r ay L i s t 还有一个比较大的缺点就是不适应于多线程环境࿰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值