ArrayList
是 Java 中的一个动态数组实现,它继承自 AbstractList
并实现了 List
接口。ArrayList
提供了基于数组的实现,允许快速随机访问。由于它是动态数组,当数组容量不足以容纳更多元素时,它会进行自动扩容。ArrayList
是非线程安全的,意味着在单线程环境中它提供了较好的性能,但在多线程环境中需要额外的同步措施来保证线程安全。ArrayList
允许存储 null
元素,并且支持快速的元素插入和删除操作,尤其是在列表的末尾。它通常用于实现对元素顺序有要求的场景,如列表、堆栈等。
1、 ArrayList
ArrayList
是 Java 集合框架中的一个非常核心的类,实现了 List
接口。以下是 ArrayList
的设计:
设计思考:
- 需求场景 :
- 在许多编程任务中,需要一个能够动态增长和收缩的数组。例如,在实现数据集合、缓冲区管理、实现其他数据结构(如栈、队列)等场景中,动态数组是非常有用的。
- 现有技术局限性 :
- 传统的数组类型在 Java 中是固定长度的,一旦创建,其大小不能改变,这限制了其在需要动态大小管理时的使用。
- 技术融合 :
ArrayList
融合了动态数组的概念,提供了一个能够根据需要自动调整大小的数组。
- 设计理念 :
ArrayList
提供了一个能够根据添加元素的数量动态增长的数组,同时保持了随机访问的能力,使其在执行索引位置的查找时非常高效。
- 实现方式 :
ArrayList
内部使用一个可变大小的数组(默认为空,随着元素添加自动扩容)来存储元素,当数组容量不足以容纳更多元素时,会自动创建一个更大的新数组,并将旧数组中的元素复制到新数组中。
2、 数据结构
图说明:
- ArrayList :
- Java 集合框架中的一个类,实现了
List
接口。
- Java 集合框架中的一个类,实现了
- Object[] elementData :
ArrayList
内部使用一个动态数组来存储元素,这个数组的类型是Object[]
,可以存储任何类型的对象。- 当数组容量不足以存储更多元素时,
ArrayList
会自动进行扩容,通常是将数组大小增加到原来的1.5倍。
- int size :
- 表示
ArrayList
中实际存储的元素数量。 size
与elementData
数组的length
属性不同,length
表示数组的总容量,而size
表示当前存储的元素个数。
- 表示
3、 执行流程
图说明:
- 初始化 ArrayList :
- 创建一个空的
ArrayList
或指定初始容量的ArrayList
。
- 创建一个空的
- 检查容量 :
- 在添加元素前,检查当前数组容量是否足够。
- 添加元素 :
- 尝试将新元素添加到
ArrayList
。
- 尝试将新元素添加到
- 容量不足 :
- 如果当前容量不足以容纳新元素,进入扩容流程。
- 扩容 :
- 创建一个新的数组,容量通常是原数组的1.5倍。
- 复制旧数组到新数组 :
- 将旧数组中的所有元素复制到新数组中。
- 增加新元素 :
- 在新数组中插入新元素。
- 获取元素 :
- 根据索引获取元素。
- 索引检查 :
- 检查索引是否在有效范围内。
- 返回元素 :
- 返回指定索引处的元素。
- 删除元素 :
- 删除
ArrayList
中的指定元素。
- 删除
- 移除指定索引元素 :
- 将指定索引处的元素移除。
- 数组元素向前移动 :
- 将移除元素之后的元素向前移动一位,填补空位。
4、优点:
- 随机访问性能高 :
- 提供了常数时间复杂度的随机访问能力。
- 动态数组 :
- 可以根据需要动态增长和收缩,不需要预先指定大小。
- 实现了
List
接口 :- 提供了
List
接口定义的所有功能,包括列表操作、迭代器支持等。
- 提供了
5、缺点:
- 插入和删除性能问题 :
- 在数组中间或开始插入或删除元素可能需要 O(n) 的时间,因为需要移动后续元素。
- 内存开销
- 相比于固定大小的数组,
ArrayList
在扩容和复制旧数组时可能会有额外的内存开销。
- 相比于固定大小的数组,
- 线程不安全 :
ArrayList
本身不是线程安全的,需要外部同步来保证线程安全。
6、使用场景:
- 需要动态大小数组的场景,如实现数据集合、缓冲区管理等。
- 需要快速随机访问元素的场景。
7、类设计
8、应用案例
ArrayList
通常用于实现动态数组,它允许快速随机访问。这是一个订单处理系统,用于管理订单项:
java
import java.util.ArrayList;
import java.util.List;
// 订单项类
class OrderItem {
private String productId;
private int quantity;
public OrderItem(String productId, int quantity) {
this.productId = productId;
this.quantity = quantity;
}
// 省略 getter 和 setter 方法
}
// 订单类
class Order {
private String orderId;
private List<OrderItem> items;
public Order(String orderId) {
this.orderId = orderId;
this.items = new ArrayList<>();
}
public void addItem(OrderItem item) {
items.add(item);
}
public List<OrderItem> getItems() {
return items;
}
// 省略其他业务方法
}
// 订单管理系统类
class OrderManagementSystem {
private List<Order> orders;
public OrderManagementSystem() {
orders = new ArrayList<>();
}
public void placeOrder(Order order) {
orders.add(order);
}
public List<Order> getAllOrders() {
return orders;
}
// 省略其他业务方法
}
public class Main {
public static void main(String[] args) {
OrderManagementSystem oms = new OrderManagementSystem();
// 创建并添加订单
Order order1 = new Order("ORD001");
order1.addItem(new OrderItem("P001", 2));
order1.addItem(new OrderItem("P002", 5));
oms.placeOrder(order1);
Order order2 = new Order("ORD002");
order2.addItem(new OrderItem("P003", 8));
oms.placeOrder(order2);
// 获取所有订单
List<Order> allOrders = oms.getAllOrders();
for (Order order : allOrders) {
System.out.println("Order ID: " + order.getOrderId());
System.out.println("Items:");
for (OrderItem item : order.getItems()) {
System.out.println("Product ID: " + item.getProductId() + ", Quantity: " + item.getQuantity());
}
}
}
}