当前位置: 首页 > news >正文

ArrayList 源码解析

ArrayListJava集合框架中的一个动态数组实现,提供了可变大小的数组功能。它继承自AbstractList并实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同步外,其余跟Vector大致相同。每个ArrayList都有一个容量capacity,表示底层数组的实际大小,容器内存储元素的个数不能多于当前容量。当向容器中添加元素时,如果容量不足,容器会自动增大底层数组的大小。

一、成员变量

在这里插入图片描述

size(), isEmpty(), get(),set()方法均能在常数时间内完成,add()方法的时间开销跟插入位置有关,addAll()方法的时间开销跟添加元素的个数成正比。其余方法大都是线性时间。为追求效率,ArrayList没有实现同步synchronized,如果需要多个线程并发访问,用户可以手动同步,也可使用Vector替代。

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = {};private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};transient Object[] elementData; // non-private to simplify nested class accessprivate int size;
}

【1】DEFAULT_CAPACITY:默认初始容量为10
【2】EMPTY_ELEMENTDATA:空数组实例,用于空实例。
【3】DEFAULTCAPACITY_EMPTY_ELEMENTDATA:默认容量为空数组实例。
【4】elementData:存储元素的数组。
【5】size:当前ArrayList中的元素数量。

二、构造方法

public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);}
}

【1】无参构造方法:初始化elementData为默认容量的空数组。
【2】指定初始容量的构造方法:根据传入的初始容量创建数组。

三、添加元素

public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;
}private void ensureCapacityInternal(int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}ensureExplicitCapacity(minCapacity);
}private void ensureExplicitCapacity(int minCapacity) {if (minCapacity - elementData.length > 0)grow(minCapacity);
}private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);
}

【1】add(E e):添加元素到ArrayList中。
【2】ensureCapacityInternal(size + 1):确保内部数组有足够的容量。
【3】elementData[size++] = e:将元素添加到数组中,并增加size
【4】ensureCapacityInternal(int minCapacity):检查并确保内部数组的容量。
【5】ensureExplicitCapacity(int minCapacity):如果需要,增加数组的容量。
【6】grow(int minCapacity):增加数组的容量,通常是原来容量的1.5倍。

四、获取元素

public E get(int index) {rangeCheck(index);return elementData(index);
}private void rangeCheck(int index) {if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}E elementData(int index) {return (E) elementData[index];
}

【1】get(int index):获取指定索引处的元素。
【2】rangeCheck(index):检查索引是否越界。
【3】elementData(index):返回数组中指定位置的元素。

五、删除元素

public E remove(int index) {rangeCheck(index);modCount++;E oldValue = elementData(index);int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index, numMoved);elementData[--size] = null; // clear to let GC do its workreturn oldValue;
}

【1】remove(int index):删除指定索引处的元素。
【2】rangeCheck(index):检查索引是否越界。
【3】System.arraycopy:将后续元素向前移动一位。
【4】elementData[--size] = null:将最后一个元素设为null,帮助垃圾回收。

六、大小调整

ArrayList的核心在于其动态调整大小的能力,通过grow方法来实现。当添加元素时,如果内部数组容量不足,就会创建一个更大的数组,并将旧数组中的元素复制到新数组中。

每当向数组中添加元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容,以满足添加数据的需求。数组扩容通过一个公开的方法ensureCapacity(int minCapacity)来实现。在实际添加大量元素前,我也可以使用ensureCapacity来手动增加ArrayList实例的容量,以减少递增式再分配的数量。数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。

    /*** Increases the capacity of this <tt>ArrayList</tt> instance, if* necessary, to ensure that it can hold at least the number of elements* specified by the minimum capacity argument.** @param   minCapacity   the desired minimum capacity*/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);}}private void ensureCapacityInternal(int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);}/*** The maximum size of array to allocate.* Some VMs reserve some header words in an array.* Attempts to allocate larger arrays may result in* OutOfMemoryError: Requested array size exceeds VM limit*/private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;/*** Increases the capacity to ensure that it can hold at least the* number of elements specified by the minimum capacity argument.** @param minCapacity the desired minimum capacity*/private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;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);}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}

在这里插入图片描述

七、总结

Fail-Fast机制: ArrayList也采用了快速失败的机制,通过记录modCount参数来实现。在面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

相关文章:

ArrayList 源码解析

ArrayList是Java集合框架中的一个动态数组实现&#xff0c;提供了可变大小的数组功能。它继承自AbstractList并实现了List接口&#xff0c;是顺序容器&#xff0c;即元素存放的数据与放进去的顺序相同&#xff0c;允许放入null元素&#xff0c;底层通过数组实现。除该类未实现同…...

libgit2编译

1. 源码下载 libgit2源码下载 2. 编译要求 CMake下载 CMake教程 3. 编译步骤 Prerequisites Make sure CMake on your %PATH% Build Create a build directory beneath the libgit2 source directory, and change into it: mkdir build && cd buildCreate the …...

mac新手入门(快捷键)

系统常用快捷键 基本操作 Command-Z 撤销Command-X 剪切  Command-C 拷贝&#xff08;Copy&#xff09; Option Shift Command V 纯文本拷贝 Command-V 粘贴  Command-A 全选&#xff08;All&#xff09;Command-S 保存&#xff08;Save) Command-F 查找&#xff0…...

curl 的使用详解

curl 是一个非常强大的命令行工具&#xff0c;用于通过各种协议&#xff08;如 HTTP、HTTPS、FTP 等&#xff09;传输数据。它广泛应用于测试 API、下载文件、调试网络请求等。 下面是 curl 常用功能的详解及示例&#xff1a; 基本语法 curl [options] [URL]1. 基本请求 发起…...

从基础到进阶:利用EasyCVR安防视频汇聚平台实现高效视频监控系统的五步走

随着科技的飞速发展&#xff0c;视频监控技术在社会安全、企业管理、智慧城市构建等领域扮演着越来越重要的角色。一个高效智能的视频监控管理系统不仅能够提升监控效率&#xff0c;还能在预防犯罪、事故预警、数据分析等方面发挥巨大作用。 一、需求分析 在设计视频监控管理…...

CORS漏洞及其防御措施:保护Web应用免受攻击

1. 背景- 什么是CORS&#xff1f; 在当今互联网时代&#xff0c;Web 应用程序的架构日益复杂。一个后端服务可能对应一个前端&#xff0c;也可能与多个前端进行交互。跨站资源共享&#xff08;CORS&#xff09;机制在这种复杂的架构中起着关键作用&#xff0c;但如果配置不当&…...

C语言自定义类型结构体(24)

文章目录 前言一、结构体类型的声明结构体回顾结构体的特殊声明结构体的自引用 二、结构体的内存对齐对齐规则为什么存在内存对齐&#xff1f;修改默认对齐数 三、结构体传参四、结构体实现位段什么是位段位段的内存分配位段的跨平台问题位段的应用位段使用的注意事项 总结 前言…...

补题篇--codeforces

传送门&#xff1a;Problem - 1881C - Codeforces 题目大意&#xff1a; 思路&#xff1a; 首先解决这个问题要知道 一个 ( x , y ) 顺时钟旋转 90 &#xff0c; 180 &#xff0c; 270可以得到 ( y , n - x 1 ) &#xff0c; ( n - x 1 , n - y 1 ) &#xff0c;( n - y …...

【字幕】恋上数据结构与算法之015动态数组03简单接口的实现

我们先来看一下&#xff0c;不要着急啊大家不要着急&#xff0c;这些东西我肯定会一点一点会给大家去实现&#xff0c;最终实现到跟Java官方版本差不多&#xff0c;只要我们自己实现了&#xff0c;偶尔类似的&#xff0c;你会发现你倒回去看Java官方的那个源码&#xff0c;你会…...

基于2023年网络赛赛题了解OpenCv

一、OpenCv图像读取与显示 1.图像的读取与显示 cv.imread() 图像读取&#xff0c;第一个参数是照片的位置一般是完整路径&#xff0c;第二个参数是指定图片输出的样式 cv.IMREAD_COLOR: 加载彩色图像。任何图像的透明度都会被忽视。&#xff08;默认模式&#xff09;。cv.I…...

你到底更适合买虚拟主机还是服务器?

前言 在当今数字化的时代&#xff0c;选择合适的网络服务平台对于个人和企业来说至关重要。无论是搭建个人博客、运营企业网站还是开发游戏&#xff0c;服务器的选择都会直接影响到项目的成本、性能以及用户体验。那么&#xff0c;你到底适合虚拟主机还是服务器呢&#xff1f;…...

linux手册翻译 addr2line

名称 addr2line 将地址转换为文件名和代码行数 简介 addr2line [-a|--addresses][-b bfdname|--targetbfdname][-C|--demangle[style]][-r|--no-recurse-limit][-R|--recurse-limit][-e filename|--exefilename][-f|--functions] [-s|--basename][-i|--inlines][-p|--pretty-…...

python-素数中的等差数列

题目描述 质数是在数论中很有意思的数&#xff0c;有很多题都可以围绕它来出&#xff0c;就如你眼前所见的这道题。 给定一个闭区间 [a,b] ,将此范围内的所有素数进行从小到大排序&#xff0c;对于连续的素数&#xff0c;我们可以发现很多等差数列(元素个数大于等于 3 )&#x…...

Unity3D 服务器AStar寻路客户端位置同步显示验证详解

在游戏开发中&#xff0c;经常需要在服务器和客户端之间同步玩家的位置信息&#xff0c;以便其他玩家可以看到他们的移动。本文将详细介绍如何在Unity 3D中使用AStar算法进行路径规划&#xff0c;并在服务器和客户端之间同步玩家的位置信息。 对惹&#xff0c;这里有一个游戏开…...

无人机之悬停精度篇

无人机的悬停精度是指无人机在无GPS信号或其他外部定位辅助下&#xff0c;能够保持在一个固定空间位置时的精度。这一精度受到多种因素的影响&#xff0c;包括但不限于风速、气压、温度、湿度以及无人机自身的姿态稳定性等。以下是对无人机悬停精度的详细分析&#xff1a; 一、…...

力扣题解2848

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述&#xff08;简单&#xff09;&#xff1a; 与车相交的点 给你一个下标从 0 开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标 i&#xff0c;nums[i] [starti, endi] &…...

电子电气架构---智能汽车应该是怎么样的架构?

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…...

无心剑七绝《中秋相思》

七绝中秋相思 中秋月满意深长 百代江阳老窖香 莫道天涯情不尽 相思寸寸赋华章 2023年9月29日 平水韵七阳平韵 这首诗七绝《中秋相思》由无心剑所作&#xff0c;以其深情的笔触描绘了中秋夜的相思之情。 诗中首句“中秋月满意深长”即以中秋圆月为起点&#xff0c;勾勒出了一幅…...

Python画笔案例-051 绘制赵爽弦图

1、绘制赵爽弦图 通过 python 的turtle 库绘制 赵爽弦图&#xff0c;如下图&#xff1a; 2、实现代码 绘制 赵爽弦图&#xff0c;以下为实现代码&#xff1a; """赵爽弦图.py本程序演录了如何自定义形状&#xff0c;如何把它添加到造型字典。赵爽弦图是用来证明…...

SEGGERS实时系统embOS推出Linux端模拟器

SEGGER 发布了两个新的 embOS 仿真模拟器&#xff1a;embOS Sim Linux 和 embOS-MPU Sim Linux。 通过模拟 Linux 主机系统上的硬件&#xff0c;取代物理硬件&#xff0c;为开发人员提供了一种无缝的方式来构建原型和测试应用程序。 embOS Sim Linux 端口支持 32 位和 64 位系…...

AI建站工具避坑指南:10个高频问题与真相解答

面对AI建站这个新事物&#xff0c;心动的人多&#xff0c;但真正敢下手的人&#xff0c;心里都藏着不少问号。“这东西靠谱吗&#xff1f;”“我的数据会不会丢了&#xff1f;”“用这个做了网站&#xff0c;以后会不会被圈住&#xff1f;”这些顾虑非常正常。今天这篇文章&…...

2025最权威的五大AI科研网站解析与推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 毕业论文写作领域里人工智能技术的应用&#xff0c;带来了好多积极影响&#xff0c;明显提高…...

告别Python!用C语言和llama.cpp API打造你的第一个本地大模型应用(附完整代码)

从Python到C语言&#xff1a;用llama.cpp构建高性能大模型推理引擎 当Python成为大模型开发的主流选择时&#xff0c;性能瓶颈也随之而来。对于需要低延迟、高吞吐的生产环境&#xff0c;C语言的性能优势开始显现。本文将带你从零开始&#xff0c;用llama.cpp的C API构建一个完…...

告别混乱!用这7款Chrome书签插件,5分钟搞定你的浏览器收藏夹整理

7款Chrome书签插件打造高效数字工作流&#xff1a;从混乱到秩序的全套解决方案 每次打开浏览器&#xff0c;面对满屏杂乱无章的书签&#xff0c;你是否感到无从下手&#xff1f;那些曾经精心收藏的网页链接&#xff0c;如今却成了数字空间的"垃圾堆"。这不是你一个人…...

6、深入解析transforms.RandomAffine():参数详解与实战应用

1. 什么是RandomAffine变换&#xff1f; RandomAffine是PyTorch中torchvision.transforms模块提供的一个非常实用的图像增强方法。简单来说&#xff0c;它能够对图像进行一系列随机的仿射变换操作。你可能要问&#xff1a;什么是仿射变换&#xff1f;其实它就是我们日常生活中常…...

MALSync快速入门:5分钟掌握自动剧集追踪技巧

MALSync快速入门&#xff1a;5分钟掌握自动剧集追踪技巧 【免费下载链接】MALSync Integrates MyAnimeList/AniList/Kitsu/Simkl into various sites, with auto episode tracking. 项目地址: https://gitcode.com/gh_mirrors/ma/MALSync MALSync是一款强大的浏览器扩展…...

深入解析LSPosed框架:5个实战技巧提升Android Hook开发效率

深入解析LSPosed框架&#xff1a;5个实战技巧提升Android Hook开发效率 【免费下载链接】LSPosed_mod My changes to LSPosed 项目地址: https://gitcode.com/GitHub_Trending/ls/LSPosed_mod LSPosed是Android生态中革命性的Hook框架&#xff0c;为开发者提供了在不修改…...

抖音下载器技术解构:多策略协同架构与智能反爬机制深度剖析

抖音下载器技术解构&#xff1a;多策略协同架构与智能反爬机制深度剖析 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback …...

Palworld存档转换工具终极指南:轻松编辑游戏数据的完整方案

Palworld存档转换工具终极指南&#xff1a;轻松编辑游戏数据的完整方案 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools Palworld存档工具是一个强…...

OpenClaw人人养虾:健康检查(macOS)

如何从菜单栏应用查看关联频道是否健康。 菜单栏 状态点现在反映 Baileys 健康状态&#xff1a; 绿色&#xff1a;已关联 socket 最近已打开。橙色&#xff1a;正在连接/重试。红色&#xff1a;已登出或探测失败。 次要行显示 "linked auth 12m" 或显示失败原因。…...