百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

面试官:你说你看过ArrayList源码,那你说说ArrayList的初始容量

bigegpt 2024-10-12 05:06 60 浏览

以下环境是 JDK 1.8

ArrayList 的初始容量

面试官:你看过 ArrayList 的源码?

Python 小星:看过

面试官:那你说下ArrayList 的初始容量是多少?

Python 小星:10

面试官:你确定!?

......

1、ArrayList源码 -- 构造器

从源码里我们可以看到,无参构造函数,容量初始化为 0,有参构造函数的初始容量自定义。

我们也可以做个测试验证,我们通过反射获取 elementData 的长度,即是 ArrayList 的容量

输出结果:

思考哈:为什么默认长度是 10 ?

hashmap 里默认 16,是为了 hash 算法。@Python大星 认为固定长度的数组初始容量不需要考虑 hashmap 里的hash冲突,取 10 可能是不大不小的值,然后一直引用下来。就像你说为什么数组的下标都是从 0 开始,而不是从 1 开始,a [0] 就是偏移为 0 的位置。a [k] 就表示偏移 k 个元素类型大小的位置,少做一步减法,就一直被继承下来,无论是 C语言、Java语言 或者 Python 语言。

知道的小伙伴欢迎在评论下留言,也许无形中帮助了很多迷茫的人。

ArrayList 是“动态数组”-- 扩容

1、“动态”体现在 ArrayList的自动扩容上

ArrayList 如何完成一次扩容?

场景:ArrayList 初始容量是 10 ,如果再 add 一个元素,会怎样?

我们可以看到 JDK8 相比之前做了一点优化,使用了 >> 位运算

数组会按照 10 + 10 * 0.5 = 15 扩容(把原来的数组复制到另一个内存空间更大的数组中),扩容后再把指向原数的地址换到新数组。

ArrayList、LinkedList、Vector 的区别?

① Arraylist 和 Vector 是采用数组方式存储数据,所以插入数据慢,查找有下标,所以查询数据快

此数组元素数大于实际存储的数据以便增加插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,

② Vector 本身所有方法都是用 synchronized 修饰的,线程安全,所以性能上比 ArrayList 要差

③ LinkedList 使用双向链表实现存储

按序号索引数据需要进行向前或向后遍历,查找较慢,但是插入数据时只需要记录本项前后项即可,插入数据较快。

为什么说 ArrayList 不是线程安全?

1、测试

输出结果:999

可以看出和我们预期的不一致。



在 add 操作分 2 步 :

① 判断 elementData 数组容量是否满足需求

② 在 elementData 对应位置上设置值

在多个线程进行 add 操作时可能会导致 elementData 数组越界。

elementData [size++] = e 设置值的操作同样会导致线程不安全。从这儿可以看出,这步操作也不是一个原子操作,线程不安全。

LinkedList

LinkedList 内部是双向链表结构

面试官:LinkedList 为什么说查找慢?它是怎么查找的?

Python 小星:因为它是链表结构,从表头开始遍历,所以当查找元素在链表后面,会比较慢

面试官:好的。回去等通知!

废话不多说,我们看下源码

从第二张图中我们可以看出:

链表中的 index 只是标记元素的相对于链表头部(first 指向的)node 的个数 ,这样在根据 index 查询时,可以根据 index 和 size 的关系,提高查询性能。当 index 大致在链表的前半部分时(index <(size>> 1)),从链表的首部开始遍历显然更快,而当 index 大致在链表的后半部分时(index > (size >> 1)),从链表的尾部开始遍历显然更快,这样就使得查找次数从 n 次将为了 n/2 次,虽然查找算法的时间复杂度还是 O (n)。

我们都知道 LinkedList 是链表结构,那到底是单向链表还是双向链表?

由上图可以看出Linkedlist是双向链表

为什么说 Vector 过时了,弃用了?

摘选 stackoverflow 的回答

https://stackoverflow.com/questions/1386275/why-is-java-vector-and-stack-class-considered-obsolete-or-deprecated#comment12234699_1386288

首先需要说明,在 Java 8 中 ,官方并没有弃用。

① Vector 对每个单独的方法进行同步;

② 通常 我们想要同步整个操作序列。

参考 https://javaconceptoftheday.com/not-use-vector-class-code/

① 无需 vector 也能实现线程安全

可以使用 Collections 类中 synchronizedList 来实现线程安全的 ArrayList

② 线程安全的 Vector 非常耗时

Vector 类的所有方法均已同步。这使 Vector 对象线程上的每个操作都安全。但是,这很耗时。因为,您需要为Vecto r在对象上执行的每个操作获取对象锁。通常,我们需要一组操作而不是每个操作都同步。一次锁定对象,为什么每次操作都要一次又一次次地获得锁?这是耗时的,降低性能。

③ Vector 设计不好

Vector 结合 2 个功能,“可调整大小的数组” 和 “同步”。这使设计不佳,而应始终使用ArrayList类。您将拥有可调整大小的数组,每当您要使其同步时,可以使用 Collections 中 synchronizedList 来实现线程安全的 ArrayList。

除了 Vector ,还有哪些线程安全的 ArrayList ?

synchronizedList 和 CopyOnWriteArrayList


1、synchronizedList

① synchronizedList 的用法(适合对数据要求较高的情况)

SynchronizedList 的 add 方法

我们可以看出,SynchronizedList 用 synchronized 同步的是代码块,而 vector 用synchronized 同步的是方法。

【1】SynchronizedList 有很好的扩展和兼容功能。他可以将所有的 List 的子类转成线程安全的类;

【2】使用 SynchronizedList 的时候,进行遍历时要手动进行同步处理。

② CopyOnWriteArrayList (适合读多写少的场景)

1、add方法

CopyOnWriteArrayList 中 add 方法的实现(向 CopyOnWriteArrayList 里添加元素),可以发现在添加的时候是需要加锁的,写入时复制(CopyOnWrite),copy 一份新的数组进行相关的操作,在执行完修改操作后将原来集合指向新的集合来完成修改操作

2、get方法

读的时候不需要加锁,如果读的时候有多个线程正在向 CopyOnWriteArrayList 添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的 CopyOnWriteArrayList。

CopyOnWriteArrayList 缺点:

【1】 内存占有问题:很明显,两个数组同时驻扎在内存中,如果实际应用中,数据比较多,而且比较大的情况下,占用内存会比较大,针对这个其实可以用 ConcurrentHashMap 来代替。

【2】 数据一致性:CopyOnWrite 容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用 CopyOnWrite 容器


@Python大星 | 文

相关推荐

方差分析简介(方差分析通俗理解)

介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...

正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃

吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...

Python数据可视化:箱线图多种库画法

概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...

多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读

作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...

方差分析 in R语言 and Excel(方差分析r语言例题)

今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...

可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图

前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...

matplotlib 必知的 15 个图(matplotlib各种图)

施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...

R ggplot2常用图表绘制指南(ggplot2绘制折线图)

ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

Python 数据可视化常用命令备忘录

本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...

统计图的种类(统计图的种类及特点图片)

统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...

实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)

大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...

通过AI提示词让Deepseek快速生成各种类型的图表制作

在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...

数据可视化:解析箱线图(box plot)

箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...

[seaborn] seaborn学习笔记1-箱形图Boxplot

1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...