一、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底层原理、线程安全及其相关集合(面试常问)的更多相关文章

  1. 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点、主程面试常问问题详解

    本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...

  2. ArrayList底层原理

    ArrayList底层采用数组实现,访问特别快,它可以根据索引下标快速找到元素.但添加插入删除等写操作效率低,因为涉及到内存数据复制转移. ArrayList对象初始化时,无参数构造器默认容量为10, ...

  3. 从Redis分布式缓存实战入手到底层原理分析、面面俱到覆盖大厂面试考点

    概述 官方说明 Redis官网 https://redis.io/ 最新版本6.2.6 Redis中文官网 http://www.redis.cn/ 不过中文官网的同步更新维护相对要滞后不少时间,但对 ...

  4. JDK集合面试20问

    1. HashMap的内部实现原理是什么? HashMap内部实现原理是数组+链表,通过散列算法将key值散列到数组中,如果到相同的位置,则通过拉链法解决散列冲突.在JDK8中新增了红黑树结构,当Ha ...

  5. 面试常问的ArrayQueue底层实现

    public class ArrayQueue<T> extends AbstractList<T>{ //定义必要的属性,容量.数组.头指针.尾指针 private int ...

  6. 深入理解List集合框架底层原理的实现

    前言: 此篇文章讲解ArrayList和LinkedList底层实现原理.for和foreach遍历集合哪个效率会更高一些! 讲讲什么是集合框架?集合框架是为表示和操作集合而规定的一种统一的标准的体系 ...

  7. Java8线程池ThreadPoolExecutor底层原理及其源码解析

    小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...

  8. ArrayList 从源码角度剖析底层原理

    本篇文章已放到 Github github.com/sh-blog 仓库中,里面对我写的所有文章都做了分类,更加方便阅读.同时也会发布一些职位信息,持续更新中,欢迎 Star 对于 ArrayList ...

  9. 4.Java集合-ArrayList实现原理及源码分析

    一.ArrayList概述: ArrayList 是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存 ArrayList不是线程安全的,只能用在单线程的情况 ...

  10. 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法

    ==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...

随机推荐

  1. 麻了,一个操作把MySQL主从复制整崩了

    前言 最近公司某项目上反馈mysql主从复制失败,被运维部门记了一次大过,影响到了项目的验收推进,那么究竟是什么原因导致的呢?而主从复制的原理又是什么呢?本文就对排查分析的过程做一个记录. 主从复制原 ...

  2. 2022-01-24:K 距离间隔重排字符串。 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k。 所有输入的字符串

    2022-01-24:K 距离间隔重排字符串. 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k. 所有输入的字符串 ...

  3. 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 ...

  4. 2021-07-09:股票问题6。给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付

    2021-07-09:股票问题6.给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :整数 fee 代表了交易股票的手续费用.你可以无限次地完成交易,但是你每笔交易都需要付 ...

  5. CPU后面的字母含义

    M(Mobile):移动笔记本电脑标准电压,功耗小,适合笔记本,i5-4310M. U(Ultra Low Voltage):移动笔记本电脑超低电压,更小的功耗.如i5-8250U. H(Height ...

  6. Vue Element-ui 之 el-table自动滚动

    首先是 div结构布局 <div id="scrollId">//对el-table盒子设置 id 属性 <div style="height: 100 ...

  7. 3 分钟利用 FastGPT 和 Laf 将 ChatGPT 接入企业微信

    原文链接:https://forum.laf.run/d/556 FastGPT 是一个超级的 ChatGPT 平台项目,功能非常强大: 集成了 ChatGPT.GPT4 和 Claude 可以使用任 ...

  8. OODO有关账户account模块学习

    一.记账凭证(Account Move) 会计上的记账凭证,也叫会计分录,在Odoo中叫"Account Move".Account Move直译是"账户移动" ...

  9. 19.详解AQS家族的成员:CountDownLatch

    关注王有志,一个分享硬核Java技术的互金摸鱼侠 欢迎你加入Java人的提桶跑路群:共同富裕的Java人 今天我们来聊一聊AQS家族中的另一个重要成员CountDownLatch.关于CountDow ...

  10. CKS 考试题整理 (15)-镜像扫描ImagePolicyWebhook

    Context cluster 上设置了容器镜像扫描器,但尚未完全集成到cluster 的配置中. 完成后,容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用. Task 注意:你必须在 cluster ...