ArrayList----源码分析

源码中的简介:

List接口的可调整数组实现。实现所有可选列表操作,并允许所有元素,包括null。除了实现List接口之外,这个类还提供了一些方法来操作内部用于存储列表的数组的大小。(这个类大致相当于Vector,只是它是不同步的。)size、isEmpty、get、set、iterator和listiterator操作在常量时间内运行。添加操作在平摊常数时间内运行,即添加n个元素需要O(n)时间。所有其他操作都在线性时间内运行(粗略地说)。与LinkedList实现相比,常数因子较低。每个ArrayList实例都有一个容量。容量是用于存储列表中元素的数组的大小。它总是至少和列表大小一样大。

当元素被添加到ArrayList中时,它的容量会自动增长。除了添加一个元素具有恒定的平摊时间成本这一事实之外,没有指定增长策略的细节。应用程序可以在添加大量元素之前使用ensureCapacity操作来增加ArrayList实例的容量。这可能会减少增量再分配的数量。注意,这个实现是不同步的。

如果多个线程同时访问一个ArrayList实例,并且至少有一个线程在结构上修改了该列表,则必须在外部进行同步。(结构修改是任何添加或删除一个或多个元素的操作,或者显式地调整后台数组的大小;仅仅设置元素的值并不是对结构的修改。)这通常是通过对一些自然封装列表的对象进行同步来完成的。如果不存在这样的对象,则应该使用集合“包装”列表。synchronizedList方法。这最好在创建时完成,以防止对列表的意外非同步访问:list list = Collections。synchronizedList(新ArrayList(…));

这个类的iterator和listtiterator方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间,以除通过迭代器自己的remove或add方法之外的任何方式修改列表,迭代器将抛出ConcurrentModificationException。因此,在面对并发修改时,迭代器会快速而干净地失败,而不是在未来不确定的时间冒任意的、不确定的行为的风险。请注意,不能保证迭代器的快速故障行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败迭代器在尽最大努力的基础上抛出ConcurrentModificationException。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应该仅用于检测错误。

继承与实现
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
​}

ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。

ArrayList 继承于 AbstractList ,实现了 List, RandomAccess, Cloneable, java.io.Serializable 这些接口。

List : 表明它是一个列表,支持添加、删除、查找等操作,并且可以通过下标进行访问。

  • RandomAccess :这是一个标志接口,表明实现这个接口的 List 集合是支持 快速随机访问 的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。

  • Cloneable :表明它具有拷贝能力,可以进行深拷贝或浅拷贝操作。

  • Serializable : 表明它可以进行序列化操作,也就是可以将对象转换为字节流进行持久化存储或网络传输,非常方便。

ArrayList 类图

ArrayList 类图

ArrayList 和 Vector 的区别?(了解即可)
  • ArrayListList 的主要实现类,底层使用 Object[]存储,适用于频繁的查找工作,线程不安全 。

  • VectorList 的古老实现类,底层使用Object[] 存储,线程安全。

Arraylist 与 LinkedList 区别?
  • 是否保证线程安全: ArrayListLinkedList 都是不同步的,也就是不保证线程安全;

  • 底层数据结构: ArrayList 底层使用的是 Object 数组LinkedList 底层使用的是 双向链表 数据结构(JDK1.6 之前为循环链表,JDK1.7 取消了循环。注意双向链表和双向循环链表的区别,下面有介绍到!)

  • 插入和删除是否受元素位置的影响:

    • ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e)方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是 O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element)),时间复杂度就为 O(n)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。

    • LinkedList 采用链表存储,所以在头尾插入或者删除元素不受元素位置的影响(add(E e)addFirst(E e)addLast(E e)removeFirst()removeLast()),时间复杂度为 O(1),如果是要在指定位置 i 插入和删除元素的话(add(int index, E element)remove(Object o),remove(int index)), 时间复杂度为 O(n) ,因为需要先移动到指定位置再插入和删除。

  • 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而 ArrayList(实现了 RandomAccess 接口) 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。

  • 内存空间占用: ArrayList 的空间浪费主要体现在在 list 列表的结尾会预留一定的容量空间,而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放直接后继和直接前驱以及数据)。

ArrayList扩容(重点)

当我们初始化数组的时候,可以指定初始容量,如果没有选择传入值去初始化容量时,默认容量是10,当我们在不断使用add()方法添加新数据时,如果超过十这个容量时,就会触发扩容机制,在这个时候,我们回去获取当前的容量大小,将其值进行右移一位(实际上对于正数而言就是除以2)在加上原来的容量大小,此时相较于旧容量增长了1.5倍,将这个容量作为新object数组,使用Arrays类中的copyOf()方法将我们的旧数组到新数组中去。

 /*** ArrayList扩容的核心方法。*/private void grow(int minCapacity) {// oldCapacity为旧容量,newCapacity为新容量int oldCapacity = elementData.length;//将oldCapacity 右移一位,其效果相当于oldCapacity /2,//我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,int newCapacity = oldCapacity + (oldCapacity >> 1);//然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,if (newCapacity - minCapacity < 0)newCapacity = minCapacity;//再检查新容量是否超出了ArrayList所定义的最大容量,//若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE,//如果minCapacity大于MAX_ARRAY_SIZE,则新容量则为Integer.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE。if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity);}
arraylist中的克隆默认为浅克隆,如何深克隆?

// 使用流克隆ArrayList

ArrayList<Dog> clonedList = dogs.stream() .map(Dog::clone).collect(Collectors.toList());

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/45106.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TC软件许可优化解决方案

TC功能说明 Teamcenter 软件是西门子面向全球范围开发的数字化全生命周期管理&#xff08;PLM&#xff09;系统&#xff0c;将人员、产品、流程、知识有机联系在一起&#xff0c;以帮助企业实现数字化协同、数字化赋能、 数字化转型&#xff0c;从而推动企业产品创新与效率提升…

Delphi 里防止程序多次运行

Delphi 里防止程序多次运行 在dpr里加入以下红色部分代码 program Main; uses Vcl.Forms, Windows, SysUtils, uMain in uMain.pas {MainForm}; {$R *.res} Var hMutex:HWND; Ret:Integer; begin Application.Initialize; Application.MainFormOnTaskbar : T…

Java链表LinkedList经典题目

一.LinkedList的方法 首先先看一下链表的方法&#xff1a; 方法解释boolean add(E e)尾插void add(int index, E element)将 e 插入到 index 位置boolean addAll(Collection c)尾插 c 中的元素E remove(int index)删除 index 位置元素boolean remove(Object o)删除遇到的第一…

【EIScopus稳检索-高录用】第五届大数据与社会科学国际学术会议(ICBDSS 2024)

大会官网&#xff1a;www.icbdss.org 大会时间&#xff1a;2024年8月16-18日 大会地点&#xff1a;中国-上海 接受/拒稿通知&#xff1a;投稿后1-2周内 收录检索&#xff1a;EI,Scopus *所有参会者现场均可获取参会证明&#xff0c;会议通知&#xff08;邀请函&#xff09;&…

2022 RoboCom省赛题目解析

题目解析&#xff1a;这就是一题很简单的模拟&#xff0c;直接上代码&#xff1b; #include<iostream> using namespace std; const int N 10010; int arr[N]; int main() {int n , m;cin >> n >> m;int sum 0;int res 0;for(int i 0; i < n;i ) cin…

系统服务综合作业01

题目&#xff1a; 现有主机 node01 和 node02&#xff0c;完成如下需求&#xff1a; 1、在 node01 主机上提供 DNS 和 WEB 服务 2、dns 服务提供本实验所有主机名解析 3、web服务提供 www.rhce.com 虚拟主机 4、该虚拟主机的documentroot目录在 /nfs/rhce 目录 5、该目录由 no…

力扣第228题“汇总区间”

在本篇文章中&#xff0c;我们将详细解读力扣第228题“汇总区间”。通过学习本篇文章&#xff0c;读者将掌握如何遍历和汇总区间&#xff0c;并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释&#xff0c;以便于理解。 问题描述 力扣第228题“汇总区间”描…

程序使用多进程,打包.exe后,程序陷入死循环

最近写了一个深度学习程序&#xff0c;用cxfreezee打包exe后&#xff0c;在本地运行突然出现死循环&#xff0c;明明在pycharm运行一切正常。 排查了问题&#xff0c;怀疑是多进程的原因&#xff0c;解决办法&#xff1a; 在你的主程序前添加一行代码&#xff1a; if __name_…

Pandas数学函数大揭秘:让数据处理变得如此简单高效,轻松玩转数据分析新纪元!

1.导包 # 导包 import numpy as np import pandas as pd2.聚合函数 df pd.DataFrame(datanp.random.randint(0,100,size(5,3))) df01203550281552376231419335895434679917 # 列非空元素的数量 df.count()0 5 1 5 2 5 dtype: int64# 行非空元素的数量 df.count(ax…

搜索引擎算法工程师,在query理解方面,都有哪些方面的工作

一、什么是query理解&#xff1f; 通俗来讲&#xff0c;就是query整形。又可以理解为是一个转接头&#xff0c;把用户送来过来的奇奇怪怪的query&#xff08;或者说是在搜索引擎看来是奇奇怪怪的query&#xff09;转换为搜索引擎最想看到的query的。 在LLM当前能力的帮助下&a…

多输入多输出 | Matlab实现Transformer多输入多输出预测

多输入多输出 | Matlab实现Transformer多输入多输出预测 目录 多输入多输出 | Matlab实现Transformer多输入多输出预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 多输入多输出 | Matlab实现Transformer多输入多输出预测&#xff08;完整源码和数据&#xff09; 1.da…

二分查找算法——部分OJ题详解

目录 关于二分查找算法 部分OJ题详解 704.二分查找 一&#xff0c;分析题目 二&#xff0c;细节处理 三&#xff0c;题目代码 四&#xff0c;*总结朴素模板 *34.在排序数组中查找元素的第一个和最后一个位置 一&#xff0c;查找左端点 二&#xff0c;处理左端点细…

什么是Stream流

文章目录 一、创建流1.1 流的类型1.2 创建 Stream 的常见操作 二、 中间操作2.1 流的映射2.2 流的过滤2.3 其他中间操作 三、 终端操作3.1 reduce() 的使用方法3.2 *short-circuiting* 方法3.3 其他的终端操作 参考资料 一、创建流 1.1 流的类型 在 Java 8 中, 集合接口有两个…

Socks5代理为何比HTTP代理快?

在网络世界中&#xff0c;代理服务器扮演着重要的角色&#xff0c;它们能够帮助我们访问被限制的网站、提高网络安全性以及优化网络性能。其中&#xff0c;Socks5代理和HTTP代理是两种常见的代理类型。然而&#xff0c;很多用户发现&#xff0c;相较于HTTP代理&#xff0c;Sock…

awk和xargs指令

ps -ef|grep "pytest"|awk {print $2}|xargs kill-9解释&#xff1a; ps -ef|grep “pytest”&#xff1a;表示找到pytest进程awk ‘{print $2}’&#xff1a;表示将第二个域打印出来&#xff0c;这里显示的就是进程号xargs kill-9&#xff1a;表示将前面的输出结果…

【两大3D转换SDK对比】HOOPS Exchange VS. CAD Exchanger

在现代工业和工程设计领域&#xff0c;CAD数据转换工具是确保不同软件系统间数据互通的关键环节。HOOPS Exchange和CAD Exchanger是两款备受关注的工具&#xff0c;它们在功能、支持格式、性能和应用场景等方面有着显著差异。 本文将从背景、支持格式、功能和性能、应用场景等…

MySQL 条件函数/加密函数/转换函数

条件函数 IF(): 如果条件为真&#xff0c;返回一个值&#xff0c;否则返回另一个值。 -- 示例&#xff1a;根据员工的薪水返回薪水等级 SELECT name, salary, IF(salary < 3000, Low, IF(salary BETWEEN 3000 AND 7000, Medium, High)) AS salary_level FROM employ…

嵌入式ARM控制器在AGV里的应用

随着ARM技术以及芯片加工工艺的迅猛发展&#xff0c; ARM工业计算机得到了越来越广泛的应用&#xff0c;尤其在工业智慧城市、智能设备以及工业自动化控制等领域。本文将为大家详细介绍ARM控制器在AGV控制系统中的应用&#xff0c;来供大家学习和参考&#xff0c;欢迎大家一起来…

Linux磁盘-创建分区

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux磁盘涉及到的命令不是很多&#xff0c;但是在实际运维中的作用却很大&#xff0c;因为Linux系统及业务都会承载到硬盘…

2.6 计算机语言

声明&#xff1a;文章参考的《系统架构设计师教程&#xff08;第二版&#xff09;》&#xff0c;如有侵权&#xff0c;本人将立即修改和删除。 一、计算机语言的组成 计算机语言主要由一套指令组成。 指令包括表达式&#xff08;变量、常量、字面量、运算符&#xff09;、流程…