ArrayList底层原理、线程安全及其相关集合(面试常问)
一、ArrayList底层原理
1.特点及其原理:ArrayList底层基于数组实现,查找快,增删慢

2.ArrayList底层原理,初始化及调用add()方法添加元素:
默认初始化容量为10

第一次创建集合并在添加第一个元素时在底层创建一个默认长度为10的数组:
调用构造函数初始化时默认创建的是空数组


只有在调用add方法添加第一个元素时才会在底层创建默认长度为10的数组



总结:第一次创建集合并添加第一个元素时在底层创建一个默认长度为10的数组;当元素插满,会进行扩容,每次扩容到之前的1.5倍(oldCapacity + (oldCapacity >> 1,二进制右移即除二,左移乘二),如果扩容1.5倍之后容量还不够,则将所需要的最小容量minCapacity赋给数组新的容量值newCapacity;扩容之后通过数组的拷贝(使用Arrays.copyOf)来确保元素的准确性。
二、ArrayList线程安全问题
由上图add()方法可知,在ArrayList中的add方法没有做相关线程安全的处理,故ArrayList本身是线程不安全的,与之相关的线程安全的方法有:
1.Vector类
Vector和ArrayList语法相同,都继承了同一个类实现了相同的接口


Vector中的add()方法添加了synchronized关键字,故Vector类是线程安全的

但是由于Vector是直接在方法上使用synchronized锁住整个方法,并发效率低,在高并发的情况下容 易造成线程阻塞等问题。
2.使用Collections工具类
使用集合的工具类Collections提供的synchronizedList方法将线程不安全的集合类变为安全的
//将线程不安全的集合对象作为参数传入synchronizedXxx()方法中
List synchronizedList = Collections.synchronizedList(arrayList);

新new一个线程安全的SynchronizedRandomAccessList或SynchronizedList。当传入的 list 是ArrayList 时,返回 SynchronizedRandomAccessList 对象;传入 LinkedList 时,返回SynchronizedList 对象。(因为ArrayList实现了RandomAccess接口而 LinkedList 没有)

而SynchronizedRandomAccessList又继承了SynchronizedList,在调用SynchronizedRandomAccessList时构造器会调用super(list)即SynchronizedList类

可以看到SynchronizedList中的add、get、remove等方法内都加了mutex对象锁,从而实现线程安全。
与Vector比较,Vector直接锁住整个方法,而使用synchronizedList时锁住方法内部的部分代码,效率会高一点。
3.在大量并发情况下使用CopyOnWriteArrayList提高集合的效率和安全

使用Lock锁相较于Synchronized关键字更为灵活、效率更高;使用transient保证值被修改后,其它线程能够立马感知到最新值。且CopyOnWriteArrayList中只有写操作加了lock锁,而读操作(get方法)未加锁,从而提高读取效率(而synchronizedList和Vector中的get方法均加了synchronized关键字):

从 add ()方法中可以看出,CopyOnWriteArrayList 通过volatile、加锁 、 以及数组拷贝来保证了集合的线程安全。

总结:CopyOnWriteArrayList是一个读操作时无锁,写操作时使用volatile关键字、lock锁以及数组拷贝来保证线程安全的ArrayList。
三、ArrayList与相关集合的区别
1.ArrayList和LinkedList
ArrayList底层基于数组,LinkedList底层基于双链表
广泛上来说:ArrayList适合查询,LinkedList适合插入,但是如果获取的是第一个元素,或最后一个元素,LinkedList查询也很快,因为LinkedList中有两个属性分别记录了当前链表中的头结点和尾结点。

ArrayList实现了RandomAccess接口,以便在随机访问列表或顺序访问列表时提供良好的性能;而LinkedList没有实现该接口。
2.ArrayList和Vector
ArrayList同一时间允许多个线程进行访问,效率高、但是线程不安全,而Vector是线程安全的,但是效率低
ArrayList扩容是每次扩大到原来的1.5倍,Vector扩容是增加原来的两倍
ArrayList可使用集合工具类Collections的synchronizedList方法将线程不安全的ArrayList集合变为安全的,所以现在很少会使用到Vector
ArrayList底层原理、线程安全及其相关集合(面试常问)的更多相关文章
- 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点、主程面试常问问题详解
本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...
- ArrayList底层原理
ArrayList底层采用数组实现,访问特别快,它可以根据索引下标快速找到元素.但添加插入删除等写操作效率低,因为涉及到内存数据复制转移. ArrayList对象初始化时,无参数构造器默认容量为10, ...
- 从Redis分布式缓存实战入手到底层原理分析、面面俱到覆盖大厂面试考点
概述 官方说明 Redis官网 https://redis.io/ 最新版本6.2.6 Redis中文官网 http://www.redis.cn/ 不过中文官网的同步更新维护相对要滞后不少时间,但对 ...
- JDK集合面试20问
1. HashMap的内部实现原理是什么? HashMap内部实现原理是数组+链表,通过散列算法将key值散列到数组中,如果到相同的位置,则通过拉链法解决散列冲突.在JDK8中新增了红黑树结构,当Ha ...
- 面试常问的ArrayQueue底层实现
public class ArrayQueue<T> extends AbstractList<T>{ //定义必要的属性,容量.数组.头指针.尾指针 private int ...
- 深入理解List集合框架底层原理的实现
前言: 此篇文章讲解ArrayList和LinkedList底层实现原理.for和foreach遍历集合哪个效率会更高一些! 讲讲什么是集合框架?集合框架是为表示和操作集合而规定的一种统一的标准的体系 ...
- Java8线程池ThreadPoolExecutor底层原理及其源码解析
小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...
- ArrayList 从源码角度剖析底层原理
本篇文章已放到 Github github.com/sh-blog 仓库中,里面对我写的所有文章都做了分类,更加方便阅读.同时也会发布一些职位信息,持续更新中,欢迎 Star 对于 ArrayList ...
- 4.Java集合-ArrayList实现原理及源码分析
一.ArrayList概述: ArrayList 是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存 ArrayList不是线程安全的,只能用在单线程的情况 ...
- 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法
==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...
随机推荐
- 麻了,一个操作把MySQL主从复制整崩了
前言 最近公司某项目上反馈mysql主从复制失败,被运维部门记了一次大过,影响到了项目的验收推进,那么究竟是什么原因导致的呢?而主从复制的原理又是什么呢?本文就对排查分析的过程做一个记录. 主从复制原 ...
- 2022-01-24:K 距离间隔重排字符串。 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k。 所有输入的字符串
2022-01-24:K 距离间隔重排字符串. 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k. 所有输入的字符串 ...
- 2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0、n-1位置不需要达标,它们分别是最左、最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] >
2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0.n-1位置不需要达标,它们分别是最左.最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] &g ...
- 2021-07-09:股票问题6。给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付
2021-07-09:股票问题6.给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :整数 fee 代表了交易股票的手续费用.你可以无限次地完成交易,但是你每笔交易都需要付 ...
- CPU后面的字母含义
M(Mobile):移动笔记本电脑标准电压,功耗小,适合笔记本,i5-4310M. U(Ultra Low Voltage):移动笔记本电脑超低电压,更小的功耗.如i5-8250U. H(Height ...
- Vue Element-ui 之 el-table自动滚动
首先是 div结构布局 <div id="scrollId">//对el-table盒子设置 id 属性 <div style="height: 100 ...
- 3 分钟利用 FastGPT 和 Laf 将 ChatGPT 接入企业微信
原文链接:https://forum.laf.run/d/556 FastGPT 是一个超级的 ChatGPT 平台项目,功能非常强大: 集成了 ChatGPT.GPT4 和 Claude 可以使用任 ...
- OODO有关账户account模块学习
一.记账凭证(Account Move) 会计上的记账凭证,也叫会计分录,在Odoo中叫"Account Move".Account Move直译是"账户移动" ...
- 19.详解AQS家族的成员:CountDownLatch
关注王有志,一个分享硬核Java技术的互金摸鱼侠 欢迎你加入Java人的提桶跑路群:共同富裕的Java人 今天我们来聊一聊AQS家族中的另一个重要成员CountDownLatch.关于CountDow ...
- CKS 考试题整理 (15)-镜像扫描ImagePolicyWebhook
Context cluster 上设置了容器镜像扫描器,但尚未完全集成到cluster 的配置中. 完成后,容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用. Task 注意:你必须在 cluster ...