ArrayList源码解析

1、介绍

1、可扩容,允许存储任何元素,包括null。这个类提供了一些方法来操纵数组大小,大致相当于Vector类。
2、ArrayList的容量是表示存储数组元素的大小,容量至少大于列表大小,在容量不足时,会自动扩容至原来的1.5倍
3、在添加元素时会通过ensureCapacity方法来判断是否需要扩容,减少扩容的次数
4、ArrayList是线程不同步的,当多线程环境下,可以通过List list = Collections.SynchronizedList(new ArrayList(...));获取同步list
5、fail-fast机制,在遍历集合过程中,使用list的增删方法,会抛出 ConcurrentModifyException 异常,是因为迭代时调用next方法时会判断
list中的modCount的值是否与内部类Itr对象中expectedCount的一致,不一致则抛出ConcurrentModifyException。list中的增删方法都会对modCount加1
6、listIterator不仅可以向后迭代,也可以向前迭代

2、类继承图
在这里插入图片描述
1)实现Cloneable接口,支持克隆,属于浅拷贝
2)实现Serializable接口,支持序列化传输
3)实现RandomAccess接口,支持随机访问(通过数组下标快速随机访问)
4)顶层接口是Iterable,列表元素可迭代。

3、核心源码解读
构造方法和默认初始容量

package java.util;import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import sun.misc.SharedSecrets;public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{private static final long serialVersionUID = 8683452581122892189L;// 默认初始容量为10private static final int DEFAULT_CAPACITY = 10;// 空数组用于空实例private static final Object[] EMPTY_ELEMENTDATA = {};// 当没有指定列表容量时,默认为空数组,当第一次添加元素时再根据实际情况判断// 使用默认的初始化容量还是最小所需容量private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// ArrayList底层使用Object数组用来存储元素transient Object[] elementData; // non-private to simplify nested class access// 列表实际存储元素个数private int size;// 构造方法,给定初始化容量public ArrayList(int initialCapacity) {// 当给定初始化容量大于零时,按给定容量创建数组if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {// 当初始化容量为0时创建空数组this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}// 构造器,没有给定默认初始化容量,创建默认空数组public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}// 构造方法,传入Collection对象,如果Collection对象的元素不为0// 复制Collection对象中数组元素到列表数组中public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}}

添加元素和自动扩容机制

public boolean add(E e) {// 判断是否需要扩容并完成自动扩容ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;
}private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}private void ensureExplicitCapacity(int minCapacity) {// 新增元素modCount加1,用于元素迭代时fail-fast机制modCount++;// 最小所需容量是否大于当前数组长度,大于则需要扩容if (minCapacity - elementData.length > 0)grow(minCapacity);
}

调用grow方法自动扩容(minCapacity添加元素最小所需容量)
正常情况下扩容至原来的1.5倍,当扩容后的新容量大于MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8时,判断最小所需容量是否大于MAX_ARRAY_SIZE ,如果大于则使用Integer最大值,否则使用MAX_ARRAY_SIZE

private void grow(int minCapacity) {// 旧容量int oldCapacity = elementData.length;// 新容量扩容至原来容量的1.5倍(oldCapacity + oldCapacity/2)int newCapacity = oldCapacity + (oldCapacity >> 1);// 新容量仍然小于最小所需容量,则使用最小所需容量为新容量if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 新容量超过最大数组容量时,调用hugeCapacity(minCapacity);调整容量// MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8    if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 将旧数组复制到新数组中,新数组容量为newCapacity,即原来的1.5倍elementData = Arrays.copyOf(elementData, newCapacity);
}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();// 最小所需容量大于MAX_ARRAY_SIZE,则使用Integer最大值,// 否则使用MAX_ARRAY_SIZE = MAX_ARRAY_SIZE - 8;return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
}

ensureCapacity方法
在添加大量元素的时候先调用该方法进行扩容,减少扩容的次数(数组复制消耗性能)

public void ensureCapacity(int minCapacity) {int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)// any size if not default element table? 0// larger than default for default empty table. It's already// supposed to be at default size.: DEFAULT_CAPACITY;if (minCapacity > minExpand) {ensureExplicitCapacity(minCapacity);}
}

indexOf方法

// 正向迭代数组判断有相同元素存在,有则返回数组下标,否则返回-1
public int indexOf(Object o) {if (o == null) {for (int i = 0; i < size; i++)if (elementData[i]==null)return i;} else {for (int i = 0; i < size; i++)if (o.equals(elementData[i]))return i;}return -1;
}

lastIndexOf方法

// 反向迭代数组判断有相同元素存在,有则返回数组下标,否则返回-1
public int lastIndexOf(Object o) {if (o == null) {for (int i = size-1; i >= 0; i--)if (elementData[i]==null)return i;} else {for (int i = size-1; i >= 0; i--)if (o.equals(elementData[i]))return i;}return -1;
}

toArray方法

// 将列表中的数组按实际元素个数复制到新的Object数组中并返回
public Object[] toArray() {return Arrays.copyOf(elementData, size);
}
public static <T> T[] copyOf(T[] original, int newLength) {return (T[]) copyOf(original, newLength, original.getClass());
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;
}

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

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

相关文章

ElementPlus 自定义封装 el-date-picker 的快捷功能

文章目录 需求分析 需求 分析 我们看到官网上给出的案例如下&#xff0c;但是不太满足我们用户想要的快捷功能&#xff0c;因为不太多&#xff0c;因此需要我们自己封装一些&#xff0c;方法如下 外部自定义该组件的快捷内容 export const getPickerOptions () > {cons…

GitLab 服务变更提醒:中国大陆、澳门和香港用户停止提供服务(GitLab 服务停止)

目录 前言 一. 变更详情 1. 停止服务区域 2. 邮件通知 3. 新的服务提供商 4. 关键日期 5. 行动建议 二. 迁移指南 三. 注意事项 四. 相关推荐 前言 近期&#xff0c;许多位于中国大陆、澳门和香港的 GitLab 用户收到了一封来自 GitLab 官方的重要通知。根据这封邮件…

使用Grafana中按钮插件实现收发HTTP请求

最近项目中需要监控分布式集群的各项指标信息&#xff0c;需要用到PrometheusGrafana的技术栈实现对分布式集群的各个节点状态进行可视化显示&#xff0c;但是要求前端需要提供一个易用的接口让用户可以触发一些操作&#xff0c;例如负载高时进行负载均衡或弹性伸缩。网上找到的…

【前端】MVC模式详解:如何构建高效的Web应用程序?

&#x1f4a5; 欢迎来到[爱学习的小羊]的博客&#xff01;希望你能在这里发现有趣的内容和丰富的知识。同时&#xff0c;期待你分享自己的观点和见解&#xff0c;让我们一起开启精彩的交流旅程&#xff01;&#x1f31f;> 首页&#xff1a;爱学习的小羊 – 热爱AI、热爱Pyt…

对一篇单细胞RNA综述的评述:细胞和基因质控参数的选择

原文链接&#xff1a; https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6072887 摘要 单细胞RNA测序技术的发展加深了我们对于细胞作为功能单元的理解&#xff0c;不仅能基于成百到成千上万个单细胞的基因表达谱得到新的结论&#xff0c;还能发现新的具有特异基因表达谱的细胞…

【再谈设计模式】享元模式~对象共享的优化妙手

一、引言 在软件开发过程中&#xff0c;我们常常面临着创建大量细粒度对象的情况&#xff0c;这可能会导致内存占用过高、性能下降等问题。享元模式&#xff08;Flyweight Pattern&#xff09;就像是一位空间管理大师&#xff0c;它能够在不影响功能的前提下&#xff0c;有效地…

windos挂载目录到linux

验证环境麒麟V10 1: 在windows任意目录设置共享文件夹 2&#xff1a;记住网络路径\LAPTOP-86JV6NT1\gantie13_sdk 在linux中替换为本机ip级相对路径 比如本级ip是192.168.23.23&#xff0c;linux环境需要ping通本地地址 3&#xff1a; sudo apt-get install cifs-utils sud…

基于STM32单片机矿井矿工作业安全监测设计

基于STM32单片机矿井矿工作业安全监测设计 目录 项目开发背景设计实现的功能项目硬件模块组成设计思路系统功能总结使用的模块技术详情介绍总结 1. 项目开发背景 随着矿井矿工作业环境的复杂性和危险性逐渐增加&#xff0c;矿井作业安全问题引起了社会各界的广泛关注。传统的…

WebRTC服务质量(11)- Pacer机制(03) IntervalBudget

WebRTC服务质量&#xff08;01&#xff09;- Qos概述 WebRTC服务质量&#xff08;02&#xff09;- RTP协议 WebRTC服务质量&#xff08;03&#xff09;- RTCP协议 WebRTC服务质量&#xff08;04&#xff09;- 重传机制&#xff08;01) RTX NACK概述 WebRTC服务质量&#xff08;…

Java爬虫技术:按关键字搜索VIP商品详情

在数字化时代&#xff0c;电子商务平台的竞争日益激烈&#xff0c;而精准的数据采集和分析成为了企业获取竞争优势的关键。对于电商平台而言&#xff0c;能够根据用户输入的关键字快速搜索并展示VIP商品的详细信息&#xff0c;不仅能够提升用户体验&#xff0c;还能够增加销售机…

若依框架中的上传图片后如何实现回显到页面的

在日常开发中&#xff0c;总会遇到上传文件、图片等功能&#xff0c;然后本地开发的话&#xff0c;又没有像OSS、七牛等网络存储&#xff0c;这个时候通常将文件上传到本地&#xff0c;那么上传之后拿到的是本地的路径&#xff0c;存储到数据库中&#xff0c;查询的时候如何将本…

一键图片转3D模型,AI建模,一键把图片转三维模型,二维图片转3维模型,AI建模

一键图片转3D模型&#xff0c;AI建模&#xff0c;一键把图片转三维模型&#xff0c;二维图片转3维模型,AI建模&#xff0c;公测版&#xff0c;每天不定时免费开放&#xff0c;非常强大 1咱们先打开ai.glbxz.com http://ai.glbxz.com 22 2导入图片。支持单张和多张图片生成 3…

梳理你的思路(从OOP到架构设计)_设计模式Android + Composite模式

目录 1、Android Composite模式 2、范例之一 3、范例之二 1、Android Composite模式 在Android平台里&#xff0c;像Button或ImageButton等屏幕控件皆通称为View。多个View能组合在一起&#xff0c;就会各种排列方式&#xff0c;即称为「布局」 (Layout)。这Layout类别就是…

LabVIEW软件项目设计方案如何制定

制定LabVIEW软件项目设计方案需要综合考虑需求分析、架构设计、功能模块划分和时间预算等多个方面&#xff0c;确保项目开发过程高效、可控且最终满足目标要求。以下是一个详细的制定流程&#xff1a; ​ 1. 需求分析 目标定义&#xff1a;明确项目的目标&#xff0c;例如数据采…

机器学习(二)-简单线性回归

文章目录 1. 简单线性回归理论2. python通过简单线性回归预测房价2.1 预测数据2.2导入标准库2.3 导入数据2.4 划分数据集2.5 导入线性回归模块2.6 对测试集进行预测2.7 计算均方误差 J2.8 计算参数 w0、w12.9 可视化训练集拟合结果2.10 可视化测试集拟合结果2.11 保存模型2.12 …

Linux运维常见命令

vi/vim快捷键使用 1)拷贝当前行 yy ,拷贝当前行向下的5行 5yy&#xff0c;并粘贴&#xff08;输入p&#xff09;。 2)删除当前行 dd ,删除当前行向下的5行5dd 3)在文件中查找某个单词 [命令行下 /关键字&#xff0c;回车查找 ,输入n就是查找下一个 ] 4)设置文件的行号&…

MacOS下TestHubo安装配置指南

TestHubo是一款开源免费的测试管理工具&#xff0c; 下面介绍MacOS私有部署的安装与配置。TestHubo 私有部署版本更适合有严格数据安全要求的企业&#xff0c;支持在本地或专属服务器上运行&#xff0c;以实现对数据和系统的完全控制。 1、Mac 服务端安装 Mac安装包下载地址&a…

jumpserver docker安装

#安装jumpserver最新版本&#xff08;当前最新版本v4.5.0-ce&#xff09; curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash#登录 http://192.168.31.168/ 默认账号密码 admin/ChangeMe 修改后&#xff1a; ad…

VBA技术资料MF243:利用第三方软件复制PDF数据到EXCEL

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

LabVIEW生物医学信号虚拟实验平台

介绍了一款基于LabVIEW的多功能生物医学信号处理实验平台的设计和实现。平台通过实践活动加强学生对理论的理解和应用能力&#xff0c;特别是在心电图(ECG)和脑电图(EEG)的信号处理方面。实验平台包括信号的滤波、特征提取和频谱分析等功能&#xff0c;能直观体验和掌握生物医学…