目录
一、ArrayList简单概述
出身
- ArrayList是Java集合框架(Java Collections Framework)中List接口的一个实现。
- 它底层是一个动态数组,用于存储一组有序的元素。
- 注意:这个有序不是排序后的“有序”;而是创建时有序的存储,即取出的时候跟插入时的顺序一致,比如:排队的时候一个接一个的排,而不是乱排,这样的队伍就是有序的。
优点:
- ArrayList可以通过下标访问,提供了更高效的随机访问性能,同时还可以根据需要自动调整其大小。
缺点:
- ArrayList的删除元素操作可能会导致性能问题,因为删除元素时需要将后面的元素向前移一位。
- 同样ArrayList的插入元素操作可能会导致性能问题,因为插入元素时需要将后面的元素向后移一位。
ArrayList的原理
ArrayList基于数组实现,这意味着它可以使用索引快速地访问和修改元素。当数组中的元素达到其容量上限时,ArrayList会创建一个新的、更大的数组,并将现有元素复制到新数组中。这个过程称为扩容(Resizing)。扩容过程是自动进行的,开发者无需手动处理。
ArrayList的特性
-
动态扩容:ArrayList可以根据需要自动调整其大小。当元素数量超过当前容量时,它会创建一个新的、更大的数组,并将现有元素复制到新数组中。
-
随机访问:由于ArrayList是基于数组实现的,因此它提供了快速的随机访问性能。通过索引,可以直接访问和修改元素。
-
重复元素:ArrayList可以包含重复元素。
二、ArrayList的源码详解
属性
private static final long serialVersionUID = 8683452581122892189L;
/**
* 默认初始容量。
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 用于空实例的共享空数组实例。
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 用于默认大小的空实例的共享空数组实例。
* 我们将其与EMPTY_ELEMENTDATA区分开来,以了解添加第一个元素时要膨胀多少。
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存储ArrayList元素的数组缓冲区。
* ArrayList的容量就是这个数组缓冲区的长度。
* 添加第一个元素时,任何elementData==DEFAULTCAPACITY_empty_elementData
* 的空ArrayList都将扩展为DEFAULT_CAPACITY。
*/
transient Object[] elementData;
/**
* ArrayList的大小(包含的元素数)。
*/
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() {//构造一个初始容量为 10 的空列表。
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//默认值是10
}
//构造一个包含指定 collection 的元素的列表,这些元素是按照该 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;
}
}
常用方法
- 插入元素 boolean add(E e)
public boolean add(E e) {
ensureCapacityInternal(size + 1); //容量加一
elementData[size++] = e;// 从末尾加入
return true;
}
- 指定位置插入 void add(int index, E element)
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); //容量加一
// 调用System.arraycopy创建新数组,再将旧数组拷贝进去
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
- 根据下标取元素 public E get(int index)
public E get(int index) {
// 调用下标范围检查方法,检查下标是否越界,若越界抛出IndexOutOfBoundsException
rangeCheck(index);
return elementData(index);//调用查找元素方法,返回元素
}
- 根据下标用指定元素替换指定下标元素,并返回旧元素
- public E set(int index, E element)
public E set(int index, E element) {
// 调用下标范围检查方法,检查下标是否越界,若越界抛出IndexOutOfBoundsException
rangeCheck(index);
//寻找被替换元素
E oldValue = elementData(index);// 调用查找元素方法,返回元素
elementData[index] = element;// 用新元素覆盖旧元素
return oldValue;// 返回旧元素
}
- 移除此列表中指定位置上的元素public E remove(int index)
public E remove(int index) {
// 调用下标范围检查方法,检查下标是否越界,若越界抛出IndexOutOfBoundsException
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;//末尾设为null
return oldValue;//返回被移除元素
}
- 移除此列表中的所有元素 void clear()
public void clear() {
modCount++;
// 遍历列表,并将所以元素设为null
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;//容量设为0
}
三、ArrayList常用方法的演示
-
创建ArrayList:要创建一个ArrayList,可以使用以下构造方法:
- 无参构造方法:
ArrayList()
- 带有一个参数的构造方法:
ArrayList(Collection<? extends E> c)
- 带有一个初始容量参数的构造方法:
ArrayList(int initialCapacity)
- 无参构造方法:
-
添加元素:可以使用
add(E e)
方法向ArrayList中添加元素。如果需要添加多个元素,可以使用addAll(Collection<? extends E> c)
方法。 -
删除元素:可以使用
remove(Object o)
方法删除指定元素的第一个匹配项。如果要删除所有匹配的元素,可以使用removeAll(Collection<?> c)
方法。 -
修改元素:可以使用
set(int index, E element)
方法修改指定索引处的元素。 -
访问元素:可以使用
get(int index)
方法通过索引访问元素。 -
遍历元素:可以使用
迭代器(Iterator)
或增强型for循环
和for循环
遍历ArrayList中的元素。
示例代码
下面是一个简单的示例,展示了如何使用ArrayList:
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListExample {
public static void main(String[] args) {
// 创建一个ArrayList
ArrayList<String> list = new ArrayList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 使用迭代器遍历元素
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
// 使用增强型for循环遍历元素
for (String element : list) {
System.out.println(element);
}
// 使用增强型for循环遍历元素
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i)+" ");
}
// 修改元素
list.set(1, "Orange");
// 删除元素
list.remove("Banana");
// 打印ArrayList
System.out.println(list);
}
}
迭代器(Iterator)或增强型for循环和for循环遍历效率对比
- 通过上图发现,for循环效率最高,增强for循环次之,迭代器最低
- 这只是元素比较少,元素多的时候会更加明显。
最后
如果感觉有收获的话,点个赞 👍🏻 吧。
❤️❤️❤️本人菜鸟修行期,如有错误,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍