一、ArrayList的定义:
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
从上述定义可以看出:
1. ArrayList继承自AbstractList,实现了List,所以它是一个队列,支持相关的添加、删除、修改、遍历等功能。
2. ArrayList实现了RandomAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。
3. ArrayList实现了Cloneable接口,即实现clone()函数。它能被克隆。
4. ArrayList实现了java.io.Serializable接口,支持序列化。
5. ArrayList是支持泛型的。
二、ArrayList的基本属性:
ArrayList只定义了两个基本属性:存放元素的数组和数组大小。
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData;
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
三、ArrayList的构造方法:
1. 第一个构造方法(不带参数):
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this(10);
}
2. 第二个构造方法(带一个参数:初始容量):
/**
* Constructs an empty list with the specified initial capacity.
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
3. 第三个构造方法(传入一个集合)
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
四、ArrayList增加元素方法:
1. add(E e):在数组末尾增加一个元素。
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
ensureCapacity():
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
增加modCount之后,判断minCapacity(即size+1)是否大于oldCapacity(即elementData.length),若大于,则调整容量为max((oldCapacity*3)/2+1,minCapacity),调整elementData容量为新的容量,即将返回一个内容为原数组元素,大小为新容量的数组赋给elementData;否则不做操作。
因此可以看出:
ArrayList容量的拓展将导致数组元素的复制,多次拓展容量将执行多次整个数组内容的复制。若提前能大致判断list的长度,调用ensureCapacity调整容量,将有效的提高运行速度。
另外,ArrayList每次容量扩展大概是原来的1.5倍,增长二分之一。
2. add(int index, E element):在指定索引处添加元素。
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
首先判断指定位置index是否超出elementData的界限,之后调用ensureCapacity调整容量(若容量足够则不会拓展),调用System.arraycopy将elementData从index开始的size-index个元素复制到index+1至size+1的位置(即index开始的元素都向后移动一个位置),然后将index位置的值指向element。
3. addAll(Collection<? extends E> c):将一个arrayList添加到另一个arrayList中。
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
先将集合c转换成数组,根据转换后数组的程度和ArrayList的size拓展容量,之后调用System.arraycopy方法复制元素到elementData的尾部,调整size。根据返回的内容分析,只要集合c的大小不为空,即转换后的数组长度不为0则返回true。
4. addAll(int index,Collection<? extends E> c):将一个arrayList添加到另一个arrayList的指定索引处。
public boolean addAll(int index, Collection<? extends E> c) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: " + index + ", Size: " + size);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
先判断index是否越界。其他内容与addAll(Collection<? extends E> c)基本一致,只是复制的时候先将index开始的元素向后移动X(c转为数组后的长度)个位置(也是一个复制的过程),之后将数组内容复制到elementData的index位置至index+X。
五、ArrayList的删除元素方法:
1. remove(int index)方法:移除指定位置的元素。
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
首先是检查范围,修改modCount,保留将要被移除的元素,将移除位置之后的元素向前挪动一个位置,将list末尾元素置空(null),返回被移除的元素。
2. remove(Object o)方法:移除指定元素的元素。
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
首先通过代码可以看到,当移除成功后返回true,否则返回false。remove(Object o)中通过遍历element寻找是否存在传入对象,一旦找到就调用fastRemove移除对象。为什么找到了元素就知道了index,不通过remove(index)来移除元素呢?因为fastRemove跳过了判断边界的处理,因为找到元素就相当于确定了index不会超过边界,而且fastRemove并不返回被移除的元素。下面是fastRemove的代码,基本和remove(index)一致。
fastRemove():
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
3. removeRange(int fromIndex,int toIndex):移除指定范围的元素。
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);
// Let gc do its work
int newSize = size - (toIndex-fromIndex);
while (size != newSize)
elementData[--size] = null;
}
执行过程是将elementData从toIndex位置开始的元素向前移动到fromIndex,然后将toIndex位置之后的元素全部置空顺便修改size。
4. clear():清空ArrayList方法。
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
clear的时候并没有修改elementData的长度(好不容易申请、拓展来的,凭什么释放,留着搞不好还有用呢。这使得确定不再修改list内容之后最好调用trimToSize来释放掉一些空间),只是将所有元素置为null,size设置为0。即clear方法只是将数组里的元素置为null,ArrayList的大小置为0,并没有释放内存。
六、ArrayList的修改元素方法:
1. set(int index,E element): 修改指定索引位置的元素的值。
public E set(int index, E element) {
RangeCheck(index);
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
首先检查范围,用新元素替换旧元素并返回旧元素。
七、ArrayList的获取元素方法:
1. get(int index):获取指定索引的元素。
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
先调用RangeCheck方法检测索引是否越界,然后直接根据数组下标获取数组元素,由此可以看出ArrayList是元素插入慢,但是查询快(数组的查询速度是很快的)。
八、ArrayList的索引相关方法:
1. indexOf(Object):获取元素在ArrayList中索引。
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;
}
通过遍历elementData数组来判断对象是否在list中,若存在,返回元素的index([0,size-1]),若不存在则返回-1。
2. lastIndexOf():获取指定元素最后出现的索引值。
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;
}
采用了从后向前遍历element数组,若遇到Object则返回index值,若没有遇到,返回-1。
九、ArrayList的其他方法:
1. isEmpty():判断ArrayList是否为空。
public boolean isEmpty() {
return size == 0;
}
直接返回size是否等于0。
2. size():获取ArrayList的大小。
public int size() {
return size;
}
3. contains(Object):判断元素是否在ArrayList中。
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
4. toArray():将ArrayList转换成数组。
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
调用Arrays.copyOf将返回一个数组,数组内容是size个elementData的元素,即拷贝elementData从0至size-1位置的元素到新数组并返回。
以下是泛型方式写法:
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
如果传入数组的长度小于size,返回一个新的数组,大小为size,类型与传入数组相同。所传入数组长度与size相等,则将elementData复制到传入数组中并返回传入的数组。若传入数组长度大于size,除了复制elementData外,还将把返回数组的第size个元素置为空。
5. trimToSize():压缩存放元素数组的空间大小。
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
}
由于elementData的长度会被拓展,size标记的是其中包含的元素的个数。所以会出现size很小但elementData.length很大的情况,将出现空间的浪费。trimToSize将返回一个新的数组给elementData,元素内容保持不变,length很size相同,节省空间。
十、ArrayList与LinkList的比较:
1. 实现方式:ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2. 随机访问速度:因为ArrayList底层由数组实现,LinkedList是双向链表,所以ArrayList的随机访问速度要比LinkedList快。
3. 插入删除速度:因为ArrayList底层由数组实现,在0号位置插入时将移动list的所有元素,在末尾插入元素时不需要移动。LinkedList是双向链表,在任意位置插入元素所需时间均相同。所以LinkedList插入删除速度要比ArrayList快。
综上所述,在List中有较多插入和删除操作的情况下应使用LinkedList来提高效率,而有较多索引查询的时候使用ArrayList(使用增强型的for循环或Iterator遍历LinkedList效率将提高很多)。
相关推荐
基于风光负荷不确定性的微电网两阶段鲁棒优化模型:投资与运行成本的综合考虑及CCG算法的Matlab+Yamilp+CPLEX求解方法,考虑风光负荷的不确定性,构建了微电网两阶段鲁棒优化容量配置模型,第一阶段目标函数为微电网投资成本,第二阶段目标函数为微电网的运行成本。 采用CCG算法求解。 包含非线性项的线性化处理。 程序代码matlab+yamilp+CPLEX ,核心关键词: 微电网; 两阶段鲁棒优化; 容量配置模型; CCG算法; 线性化处理; MATLAB; YAMILP; CPLEX 用分号分隔每个关键词的结果为: 微电网; 两阶段鲁棒优化; 容量配置模型; CCG算法; 线性化处理; MATLAB; Yamilp; CPLEX,微电网鲁棒优化模型:两阶段成本最小化与线性化处理
西门子S7-200PLC在Z35摇臂钻床控制系统中的应用与组态王组态设计研究,98西门子S7-200PLC和组态王组态Z35摇臂钻床控制系统组态设计PLC设计 ,西门子S7-200PLC; 组态王组态; 摇臂钻床控制系统; PLC设计,西门子S7-200PLC与组态王Z35摇臂钻床控制系统组态设计
烟花代码编程python满屏-10.排队接水——我直接把水吸过来.py
基于三菱PLC的喷灌控制系统设计及组态画面实现,No.393 三菱PLC组态王组态画面基于PLC的喷灌控制设计灌溉控制 ,基于三菱PLC; 喷灌控制设计; 组态王组态画面; 灌溉控制。,基于三菱PLC的喷灌控制设计:组态王组态画面应用
基于Dijkstra算法的路径规划Matlab代码:读取黑白色地图并实现图像上的路径规划示例,读取黑白色地图,在图片上进行路径规划matlab代码 路径规划算法基于读图识别的Dijkstra算法 随意设置坐标,规划路径 示例如下 ,读取地图; 路径规划算法; Dijkstra算法; 坐标设置; 规划路径,基于Dijkstra算法的Matlab黑白色地图路径规划代码
融合空间特征的债券图表数据文本检测方法研究.pdf
基于粒子群优化与遗传算法的高速列车横向悬挂模糊PID控制技术研究:s函数建模与仿真分析详解文件,基于粒子群 遗传算法的高速列车横向悬挂模糊PID控制-s函数搭建。 赠word详解文件 ,基于粒子群; 遗传算法; 高速列车横向悬挂; 模糊PID控制; s函数搭建,基于遗传算法的高速列车悬挂PID模糊控制的S函数构建方案
一种基于Retinex的非线性彩色图像增强算法.pdf
基于因式分解的逆合成孔径雷达三维成像技术及序列因子分解法研究,逆合成孔径雷达三维成像,因式分解法,序列因子分解法。 此部分只做了因式分解的工作,假设散射点已经准确提取并得到散射点坐标矩阵,利用因式分解恢复目标三维结构 ,逆合成孔径雷达三维成像; 因式分解法; 序列因子分解; 散射点提取; 散射点坐标矩阵; 恢复目标三维结构。,利用因式分解恢复三维结构:逆合成孔径雷达三维成像技术
MATLAB R2021b环境下深度学习驱动的车道线检测算法研究与应用,MATLAB环境下一种基于深度学习的车道线检测方法 算法运行环境为matlab r2021b,执行基于深度学习的车道线检测。 if batch ~= numBatches lastFrameIdx = miniBatchSize*batch; else 压缩包=数据+程序 ,核心关键词如下: MATLAB环境; 深度学习; 车道线检测; 算法运行环境; 批处理; 压缩包 以上关键词用分号分隔为: MATLAB环境; 深度学习; 车道线检测; 算法运行环境r2021b; 批处理(batch~numBatches); 压缩包(数据+程序) 注意:最后一个关键词“压缩包”并不是直接从您提供的信息中提炼出来的,而是根据您提到的“压缩包=数据+程序”这一句推断出来的。如果这不是您想要的核心关键词,请告诉我,我会进行相应的调整。,MATLAB深度学习车道线检测算法压缩包
西门子S7-200PLC在物料自动称量控制系统中的应用:基于称重配料混合程序的组态设计与王设计PLC程序设计,74基西门子S7-200PLC的物料自动称量控制系统称重配料物料混合程序组态设计组态设计组态王设计plc程序设计 ,核心关键词:西门子S7-200PLC;自动称量控制系统;物料混合程序;组态设计;组态王设计;PLC程序设计。,西门子S7-200PLC物料自动称量控制系统称重配料程序组态设计
优化无人机侦查与目标搜索路径规划:对未知区域进行覆盖并精确寻靶的Matlab代码解析与实践指南。,无人机覆盖搜索路径规划 无人机搜索目标路径规划 无人机侦查路径规划 对未知区域进行覆盖搜索,并且寻找目标 matlab代码有详细注释,可快速上手。 ,核心关键词:无人机; 覆盖搜索路径规划; 搜索目标路径规划; 侦查路径规划; 未知区域覆盖搜索; MATLAB代码注释。,**无人机未知区域覆盖搜索及目标路径规划Matlab代码详解**
shp格式,可直接导入arcgis使用
基于博途软件编程的11层电梯控制系统:文档齐全,优质售后保障的智能运行体验,基于PLC的单部11层电梯控制系统,采用博途软件编写提供画面,文档(含接线图,流程图,IO分配表)及优质的后服务。 最终运行效果,详见上方演示视频 ,核心关键词:PLC控制;11层电梯;博途软件;画面编写;文档资料;接线图;流程图;IO分配表;售后服务;演示视频。,"博途软件控制下的11层电梯系统,高效运行效果详见演示视频"
"飞剪追剪程序:PLC与伺服同步控制完整指南,适合新手学习与参考,包含PLC程序、触摸屏程序及CAD电路图纸",飞剪追剪程序plc程序伺服程序 同步控制 适合新手学习参考 包含PLC程序+触摸屏程序+CAD电路图纸。 ,飞剪追剪程序; PLC程序; 伺服程序; 同步控制; 新手学习参考; PLC程序+触摸屏程序; CAD电路图纸,适合新手的飞剪追剪程序全套教程:PLC+伺服同步控制
使用Matlab编程:无迹卡尔曼滤波算法(UKF)的编写及其在电池SOC估计中的应用,噪声系数自适应优化方案的研究。,使用matlab编写m脚本,编写无迹卡尔曼滤波算法(UKF)估计电池SOC,注释清晰。 卡尔曼滤波算法(EKF)锂电池SOC估计,噪声系数自适应 Matlab ,matlab; 无迹卡尔曼滤波算法(UKF); 电池SOC估计; 注释清晰; 噪声系数自适应。,Matlab无迹卡尔曼滤波(UKF)用于电池SOC估计的代码实现
Ansys LS-DYNA多孔延时起爆与重复起爆模拟的完整过程解析,Ansys ls_dyna多孔延时起爆,重复起爆模拟 全过程 ,Ansys;LS_dyna;多孔延时起爆;重复起爆模拟;全过程,Ansys LS-DYNA多孔延时重复起爆模拟全过程
FPGA驱动双目视觉系统:立体匹配、视差图与深度图生成技术的研究与应用,FPGA双目视觉 立体视觉 视差图 深度图 双目立体匹配sgm sgbm tang 20k 高云fpga usb摄像头采集图像 ,FPGA双目视觉;立体视觉;视差图;深度图;双目立体匹配sgm;sgbm;高云FPGA;USB摄像头图像采集。,基于FPGA的双目视觉系统:立体匹配与深度图生成
整个手套大盘的指数图如下.docx
基于AGV全覆盖移动避障的扫地机器人路径规划算法研究:深度优先搜索与随机碰撞对比,AGV全覆盖移动避障路径规划matlab代码 扫地机器人路径规划 第一类算法 全覆盖智能算法 %% 基于深度优先搜索算法的路径规划—扫地机器人移动仿真 % 返回深度优先搜索实现全覆盖的运行次数 % 将栅格模型的每一个栅格看成一个点 % 实际中栅格模型是连续的,在计算机处理时看作离散的 % 将栅格模型抽象为标识矩阵,矩阵对应位置的标记表示栅格对应位置的状态 第二对比算法 %% 随机碰撞的路径规划—扫地机器人移动仿真 % 返回深度优先搜索实现全覆盖的运行次数 % 将栅格模型的每一个栅格看成一个点 % 实际中栅格模型是连续的,在计算机处理时看作离散的 % 将栅格模型抽象为标识矩阵,矩阵对应位置的标记表示栅格对应位置的状态 ,核心关键词: 1. AGV全覆盖移动避障 2. 路径规划 3. Matlab代码 4. 扫地机器人路径规划 5. 第一类算法 6. 全覆盖智能算法 7. 深度优先搜索算法 8. 栅格模型 9. 标识矩阵 10. 随机碰撞的路径规划,"AGV全覆盖避障路径规划:Matlab代码实现与对比"