Java ArrayList
ArrayList
是 Java 集合框架中非常常用的一种实现类,属于 List 接口的实现,它基于动态数组来实现集合,因此具有按索引快速访问元素的特点。ArrayList
允许存储 重复元素,并且是 有序的,即元素的插入顺序会被保持。
1. ArrayList 的基本特性
- 大小可变:
ArrayList
会自动调整数组的大小以适应元素的增减。初始容量是 10,当ArrayList
中的元素超过当前容量时,它会扩容(通常是扩展为原来大小的 1.5 倍)。 - 支持随机访问:通过索引访问元素的时间复杂度是 O(1)。
- 不支持线程安全:
ArrayList
不是线程安全的,如果多个线程并发修改同一个ArrayList
,需要额外的同步处理。 - 允许存储
null
:ArrayList
可以存储null
元素。
2. ArrayList 的常用构造函数
// 默认构造函数,初始容量为 10
ArrayList<E> list = new ArrayList<>();
// 指定初始容量
ArrayList<E> list = new ArrayList<>(int initialCapacity);
// 基于另一个集合创建 ArrayList
ArrayList<E> list = new ArrayList<>(Collection<? extends E> c);
3. ArrayList 常用方法
3.1 添加元素
add(E e)
:将元素添加到列表的末尾。add(int index, E element)
:在指定的索引位置插入元素。
ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add(1, "Orange"); // 在索引 1 插入 "Orange"
3.2 删除元素
remove(Object o)
:删除第一次出现的指定元素。remove(int index)
:删除指定位置的元素。clear()
:删除所有元素。
list.remove("Banana"); // 删除 "Banana"
list.remove(0); // 删除索引为 0 的元素
list.clear(); // 清空 ArrayList
3.3 访问元素
get(int index)
:获取指定索引位置的元素。set(int index, E element)
:替换指定索引位置的元素。
String fruit = list.get(1); // 获取索引为 1 的元素
list.set(1, "Grapes"); // 替换索引为 1 的元素
3.4 查询元素
contains(Object o)
:检查列表是否包含某个元素。indexOf(Object o)
:返回指定元素首次出现的索引,如果没有找到返回 -1。size()
:返回ArrayList
中的元素个数。isEmpty()
:判断ArrayList
是否为空。
boolean containsApple = list.contains("Apple"); // 检查是否包含 "Apple"
int index = list.indexOf("Grapes"); // 获取 "Grapes" 的索引
int size = list.size(); // 获取 ArrayList 的大小
boolean isEmpty = list.isEmpty(); // 判断是否为空
3.5 遍历元素
- 使用 for-each 循环:
for (String fruit : list) {
System.out.println(fruit);
}
- 使用 Iterator:
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
- 使用 for 循环:
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
3.6 转换为数组
toArray()
:将ArrayList
转换为数组。
Object[] array = list.toArray();
toArray(T[] a)
:将ArrayList
转换为指定类型的数组。
String[] array = list.toArray(new String[0]);
3.7 其他常用方法
removeAll(Collection<?> c)
:删除列表中所有与给定集合c
相同的元素。retainAll(Collection<?> c)
:保留列表中所有与给定集合c
相同的元素。subList(int fromIndex, int toIndex)
:返回指定范围的子列表(不包括toIndex
)。ensureCapacity(int minCapacity)
:确保列表有足够的容量来容纳至少minCapacity
个元素。
4. ArrayList 的性能
- 访问元素:由于
ArrayList
是基于动态数组实现的,获取元素是 O(1) 的时间复杂度。 - 添加元素:如果是在末尾添加元素,时间复杂度为 O(1),但是当需要扩容时(元素数量超过当前容量),时间复杂度是 O(n)。
- 插入和删除元素:在中间或头部插入或删除元素时,需要移动其他元素,因此时间复杂度为 O(n)。
5. 使用 ArrayList 的场景
- 随机访问:
ArrayList
在需要频繁通过索引访问元素的场景中表现优异。 - 元素个数变化较少:当元素个数变化较少时,使用
ArrayList
很方便,因为它的查询效率高。 - 排序操作:由于
ArrayList
允许访问所有元素,因此可以通过集合类中的sort()
方法快速排序。
6. 线程安全问题
ArrayList
默认不是线程安全的。如果在多线程环境中同时访问和修改 ArrayList
,则可能会导致数据不一致问题。在这种情况下,可以使用:
Collections.synchronizedList()
:将ArrayList
包装成线程安全的列表。CopyOnWriteArrayList
:适用于写操作较少的多线程环境,它会在每次修改时复制整个数组。
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
7. ArrayList 与 LinkedList 的比较
特性 | ArrayList | LinkedList |
---|---|---|
底层实现 | 动态数组 | 双向链表 |
随机访问 | 快速 O(1) | 慢 O(n) |
插入/删除操作 | 慢 O(n),尤其是中间位置 | 快 O(1),在头尾插入和删除较快 |
内存占用 | 内存占用较小 | 每个节点额外存储前后节点引用 |
适用场景 | 频繁查询,少量插入删除操作 | 频繁插入删除,尤其是头尾位置操作 |
小结
ArrayList
是一个灵活且高效的集合类,适用于需要快速随机访问和较少修改的场景。它是 Java 集合框架中最常用的类之一,对于需要频繁读取但较少插入或删除元素的应用场景非常合适。如果需要更频繁的插入和删除操作,可能需要考虑 LinkedList
。更多详细内容请关注其他相关文章。