ArrayList 概述
ArrayList 是 Java 集合框架中的一个类,实现了 List 接口。它使用动态数组来存储元素,因此能够快速地进行随机访问和迭代操作。与 LinkedList 相比,ArrayList 提供了更快的查找和更新操作,但在插入和删除大量元素时性能较差。
内部实现
ArrayList 的内部使用一个可动态调整大小的数组来存储元素。当数组满时,会创建一个新的、更大的数组并将旧数组的元素复制到新数组中。这种扩展策略使得 ArrayList 在插入元素时具有摊销的时间复杂度,即大多数插入操作的时间复杂度为 O(1),但在需要扩展数组时,单次插入的时间复杂度为 O(n)。
常用构造函数
无参构造函数:创建一个初始容量为 10 的空列表。
ArrayList
指定初始容量:创建一个指定初始容量的空列表。
ArrayList
从另一个集合创建:创建一个包含指定集合元素的列表。
List
ArrayList
常用方法
1. 添加元素
添加到末尾:
list.add("element");
添加到指定位置:
list.add(1, "element");
添加另一个集合的所有元素:
List
list.addAll(anotherList);
添加另一个集合的所有元素到指定位置:
list.addAll(2, anotherList);
2. 访问元素
通过索引获取元素:
String element = list.get(0);
获取列表大小:
int size = list.size();
3. 修改元素
修改指定位置的元素:
String oldElement = list.set(1, "newElement");
4. 删除元素
删除指定位置的元素:
String removedElement = list.remove(1);
删除首次出现的指定元素:
boolean isRemoved = list.remove("element");
清空列表:
list.clear();
5. 遍历列表
传统 for 循环:
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
增强 for 循环:
for (String element : list) {
System.out.println(element);
}
使用迭代器:
Iterator
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
6. 检查元素
检查列表是否为空:
boolean isEmpty = list.isEmpty();
检查列表是否包含某元素:
boolean contains = list.contains("element");
获取元素的第一次出现位置:
int index = list.indexOf("element");
获取元素的最后一次出现位置:
int lastIndex = list.lastIndexOf("element");
7. 转换为数组
将列表转换为数组:
Object[] array = list.toArray();
将列表转换为指定类型的数组:
String[] array = list.toArray(new String[0]);
8. 克隆列表
创建列表的浅表副本:
ArrayList
9. 线程安全
ArrayList 是非线程安全的。如果需要在多线程环境中使用,可以使用 Collections.synchronizedList 方法来包装 ArrayList。
List
线程安全的注意事项:即使使用 Collections.synchronizedList 包装 ArrayList,在遍历集合时仍需要手动同步以避免并发修改异常(ConcurrentModificationException)。
List
synchronized (synchronizedList) {
Iterator
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
示例代码
下面是一个包含上述操作的综合示例:
import java.util.*;
public class ArrayListExample {
public static void main(String[] args) {
// 创建 ArrayList
ArrayList
// 添加元素
list.add("d");
list.add(1, "e");
list.addAll(Arrays.asList("f", "g", "h"));
// 访问元素
System.out.println("Element at index 2: " + list.get(2));
System.out.println("List size: " + list.size());
// 修改元素
list.set(1, "x");
// 删除元素
list.remove(2);
list.remove("g");
// 遍历列表
for (String element : list) {
System.out.println(element);
}
// 检查元素
System.out.println("List contains 'a': " + list.contains("a"));
System.out.println("Index of 'a': " + list.indexOf("a"));
// 转换为数组
String[] array = list.toArray(new String[0]);
System.out.println("Array: " + Arrays.toString(array));
// 克隆列表
ArrayList
System.out.println("Cloned list: " + clonedList);
// 线程安全的列表
List
synchronized (synchronizedList) {
Iterator
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
}
输出结果
创建 ArrayList:
ArrayList
初始列表内容为:["a", "b", "c"]
添加元素:
list.add("d"); // ["a", "b", "c", "d"]
list.add(1, "e"); // ["a", "e", "b", "c", "d"]
list.addAll(Arrays.asList("f", "g", "h")); // ["a", "e", "b", "c", "d", "f", "g", "h"]
访问元素:
System.out.println("Element at index 2: " + list.get(2)); // 输出: Element at index 2: b
System.out.println("List size: " + list.size()); // 输出: List size: 8
修改元素:
list.set(1, "x"); // ["a", "x", "b", "c", "d", "f", "g", "h"]
删除元素:
list.remove(2); // ["a", "x", "c", "d", "f", "g", "h"]
list.remove("g"); // ["a", "x", "c", "d", "f", "h"]
遍历列表:
for (String element : list) {
System.out.println(element);
}
输出:
a
x
c
d
f
h
检查元素:
System.out.println("List contains 'a': " + list.contains("a")); // 输出: List contains 'a': true
System.out.println("Index of 'a': " + list.indexOf("a")); // 输出: Index of 'a': 0
转换为数组:
String[] array = list.toArray(new String[0]);
System.out.println("Array: " + Arrays.toString(array)); // 输出: Array: [a, x, c, d, f, h]
克隆列表:
ArrayList
System.out.println("Cloned list: " + clonedList); // 输出: Cloned list: [a, x, c, d, f, h]
线程安全的列表:
List
synchronized (synchronizedList) {
Iterator
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
输出与遍历列表相同:
a
x
c
d
f
h
完整的输出结果如下:
Element at index 2: b
List size: 8
a
x
c
d
f
h
List contains 'a': true
Index of 'a': 0
Array: [a, x, c, d, f, h]
Cloned list: [a, x, c, d, f, h]
a
x
c
d
f
h
性能特征
随机访问:由于底层使用数组,ArrayList 提供了 O(1) 时间复杂度的随机访问。插入和删除:在末尾插入或删除元素的时间复杂度为 O(1),在中间插入或删除元素的时间复杂度为 O(n)。扩展机制:当数组满时,ArrayList 会将其容量增加到原来的 1.5 倍(具体倍数可能因 JVM 实现而异)。总结
ArrayList 是一种灵活且高效的数据结构,适用于频繁的随机访问和少量插入、删除操作的场景。了解其内部实现和性能特征有助于在实际开发中合理使用 ArrayList,从而提高程序的效率和可维护性。