- 大小动态性:ArrayList的大小是动态的,可以根据需要动态扩展和收缩。而普通数组的大小是固定的,一旦创建就无法改变。
- 自动扩展:当ArrayList中的元素数量超过当前容量时,ArrayList会自动进行扩展,而普通数组需要手动重新分配内存并复制数据。
- 插入和删除元素效率高:ArrayList支持在任意位置插入和删除元素,而普通数组在插入和删除元素时需要移动其他元素。
- 内置方法和功能:ArrayList提供了许多便捷的方法和功能,如添加、删除、查找等操作,使其更易于使用和操作。
总的来说,ArrayList相对于普通数组来说更加灵活、便捷,并且具有更高的操作效率。因此,在大多数情况下,使用ArrayList比使用普通数组更加方便和实用。
二、 内部实现
2.1 数据结构:动态数组
在Java中,ArrayList是一个动态数组实现的类,它是基于数组实现的动态数组,可以自动扩容。下面是ArrayList的动态数组原理:
- 内部数组:ArrayList内部使用一个数组来存储元素。当创建一个ArrayList时,会初始化一个初始容量的数组。
- 自动扩容:当向ArrayList中添加元素时,如果当前数组已满,ArrayList会创建一个新的更大容量的数组,并将原数组中的元素复制到新数组中,然后将新元素添加到新数组中。
- 扩容策略:ArrayList的扩容策略是在每次扩容时将当前容量扩大为原来的
1.5倍
,这种策略既能够保证空间利用率,又能够减少因频繁扩容而带来的性能开销。 - 随机访问:由于ArrayList内部基于数组实现,因此支持随机访问,可以通过索引直接访问数组中的元素,时间复杂度为
O(1)
。
总的来说,ArrayList通过动态扩容的方式,利用数组实现了一个动态数组,提供了高效的随机访问和动态增删元素的功能。
2.2 添加元素:add()方法的实现原理
在Java中,ArrayList的add()
方法用于向ArrayList中添加元素。
其实现原理如下:
- 在调用add()方法时,先检查当前ArrayList的大小和容量(即存储空间是否足够)。
- 如果当前容量不够,就进行扩容操作。一般情况下,会创建一个新的数组,将原数组中的元素复制到新数组中,并且为新数组分配更大的存储空间。
- 然后将要添加的元素放入ArrayList的内部数组中,并更新ArrayList的大小。
- 如果添加成功,则返回
true
,如果添加失败,则返回false
。
总的来说,ArrayList的add()方法实现原理就是对内部数组的扩容和元素的添加操作。
2.3 扩容机制:ensureCapacity()方法的实现原理
在使用ArrayList时,如果我们预先知道将要插入的元素数量,可以使用ensureCapacity()
方法来预先分配内部数组大小。调用了一个名为ensureCapacityInternal()
的私有方法。这个方法首先会判断当前内部数组是否已经足够大来容纳新增的元素,如果不够大,则会进行扩容:
- 如果当前内部数组为空,则直接扩容到指定容量大小。
- 否则,计算出新数组的容量大小,这个容量大小取决于原始数组的大小和扩容因子(默认为1.5倍)。
- 如果新数组容量大小小于所需容量,则按照所需容量分配新的数组;否则,按照新数组容量大小分配新的数组。
- 将原始数组中的元素复制到新数组中,并将新数组赋值给ArrayList对象的
elementData
变量。
import java.util.ArrayList;
public class EnsureCapacityExample {
public static void main(String[] args) {
// 创建一个空的ArrayList
ArrayList<Strin