Java List全面解析:从入门到精通
Java List全面解析:从入门到精通
引言
一、List接口概述
1.1 List接口的特点
- 有序性:元素按照插入顺序保存
- 可重复性:允许存储重复元素
- 索引访问:可以通过索引位置访问元素
- 动态扩容:大多数实现类支持自动扩容
1.2 List接口的核心方法
import java.util.*;
public class ListBasicOperations {
public static void main(String[] args) {
// 创建List
List<String> list = new ArrayList<>();
// 添加元素
list.add("Java");
list.add("Python");
list.add("C++");
list.add(1, "JavaScript"); // 在指定位置插入
System.out.println("初始列表: " + list);
// 获取元素
String element = list.get(2);
System.out.println("索引2的元素: " + element);
// 修改元素
list.set(1, "TypeScript");
System.out.println("修改后列表: " + list);
// 删除元素
list.remove("C++");
list.remove(0);
System.out.println("删除后列表: " + list);
// 查找元素
int index = list.indexOf("TypeScript");
System.out.println("TypeScript的索引: " + index);
// 检查包含
boolean contains = list.contains("Java");
System.out.println("是否包含Java: " + contains);
// 列表大小
System.out.println("列表大小: " + list.size());
// 清空列表
list.clear();
System.out.println("清空后列表: " + list);
System.out.println("列表是否为空: " + list.isEmpty());
}
}
二、List的主要实现类
2.1 ArrayList
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
// ArrayList的创建和基本操作
ArrayList<Integer> arrayList = new ArrayList<>();
// 添加元素
for (int i = 1; i <= 10; i++) {
arrayList.add(i * 10);
}
System.out.println("ArrayList: " + arrayList);
// 容量相关操作
arrayList.ensureCapacity(20); // 确保最小容量
arrayList.trimToSize(); // 调整容量到当前大小
// 性能测试:随机访问
long startTime = System.nanoTime();
for (int i = 0; i < arrayList.size(); i++) {
Integer value = arrayList.get(i);
}
long endTime = System.nanoTime();
System.out.println("ArrayList随机访问耗时: " + (endTime - startTime) + "纳秒");
// 子列表操作
List<Integer> subList = arrayList.subList(2, 5);
System.out.println("子列表(2-5): " + subList);
// 批量操作
ArrayList<Integer> anotherList = new ArrayList<>(Arrays.asList(100, 110, 120));
arrayList.addAll(anotherList);
System.out.println("添加另一个列表后: " + arrayList);
// 转换为数组
Integer[] array = arrayList.toArray(new Integer[0]);
System.out.println("转换为数组: " + Arrays.toString(array));
}
}
2.2 LinkedList
import java.util.*;
public class LinkedListDemo {
public static void main(String[] args) {
// LinkedList的创建和基本操作
LinkedList<String> linkedList = new LinkedList<>();
// 添加元素
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.addFirst("Orange"); // 添加到开头
linkedList.addLast("Grape"); // 添加到结尾
System.out.println("LinkedList: " + linkedList);
// 队列操作
System.out.println("头部元素: " + linkedList.peek());
System.out.println("尾部元素: " + linkedList.peekLast());
// 栈操作
linkedList.push("Strawberry"); // 压栈
System.out.println("压栈后: " + linkedList);
String popped = linkedList.pop(); // 出栈
System.out.println("出栈元素: " + popped);
System.out.println("出栈后: " + linkedList);
// 性能测试:插入和删除
long startTime = System.nanoTime();
linkedList.add(2, "Mango");
long endTime = System.nanoTime();
System.out.println("LinkedList插入耗时: " + (endTime - startTime) + "纳秒");
// 双向遍历
System.out.println("正向遍历:");
ListIterator<String> iterator = linkedList.listIterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println("\n反向遍历:");
while (iterator.hasPrevious()) {
System.out.print(iterator.previous() + " ");
}
System.out.println();
// 删除操作
linkedList.removeFirst();
linkedList.removeLast();
System.out.println("删除首尾后: " + linkedList);
}
}
2.3 Vector
import java.util.*;
public class VectorDemo {
public static void main(String[] args) {
// Vector的创建
Vector<Integer> vector = new Vector<>();
// 添加元素
for (int i = 1; i <= 5; i++) {
vector.add(i);
}
System.out.println("Vector: " + vector);
// 设置容量和增量
Vector<Integer> vectorWithCapacity = new Vector<>(10, 5);
for (int i = 1; i <= 15; i++) {
vectorWithCapacity.add(i);
}
System.out.println("带容量的Vector: " + vectorWithCapacity);
System.out.println("当前容量: " + vectorWithCapacity.capacity());
// 枚举遍历
System.out.println("枚举遍历:");
Enumeration<Integer> enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
System.out.print(enumeration.nextElement() + " ");
}
System.out.println();
// 元素操作
vector.setSize(8); // 设置大小
System.out.println("设置大小后: " + vector);
}
}
三、List的高级用法
3.1 遍历方式比较
import java.util.*;
public class ListIterationMethods {
public static void main(String[] args) {
List<String> languages = Arrays.asList("Java", "Python", "JavaScript", "C++", "Go");
System.out.println("=== 不同遍历方式比较 ===");
// 1. for循环遍历
System.out.println("1. for循环遍历:");
long startTime = System.nanoTime();
for (int i = 0; i < languages.size(); i++) {
System.out.print(languages.get(i) + " ");
}
long endTime = System.nanoTime();
System.out.println("\n耗时: " + (endTime - startTime) + "纳秒");
// 2. 增强for循环
System.out.println("\n2. 增强for循环:");
startTime = System.nanoTime();
for (String language : languages) {
System.out.print(language + " ");
}
endTime = System.nanoTime();
System.out.println("\n耗时: " + (endTime - startTime) + "纳秒");
// 3. 迭代器遍历
System.out.println("\n3. 迭代器遍历:");
startTime = System.nanoTime();
Iterator<String> iterator = languages.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
endTime = System.nanoTime();
System.out.println("\n耗时: " + (endTime - startTime) + "纳秒");
// 4. ListIterator双向遍历
System.out.println("\n4. ListIterator双向遍历:");
ListIterator<String> listIterator = languages.listIterator();
System.out.println("正向:");
while (listIterator.hasNext()) {
System.out.print(listIterator.next() + " ");
}
System.out.println("\n反向:");
while (listIterator.hasPrevious()) {
System.out.print(listIterator.previous() + " ");
}
System.out.println();
// 5. forEach + Lambda
System.out.println("\n5. forEach + Lambda:");
startTime = System.nanoTime();
languages.forEach(language -> System.out.print(language + " "));
endTime = System.nanoTime();
System.out.println("\n耗时: " + (endTime - startTime) + "纳秒");
// 6. 并行流遍历
System.out.println("\n6. 并行流遍历:");
startTime = System.nanoTime();
languages.parallelStream().forEach(language ->
System.out.print(Thread.currentThread().getName() + ":" + language + " "));
endTime = System.nanoTime();
System.out.println("\n耗时: " + (endTime - startTime) + "纳秒");
}
}
3.2 排序和搜索
import java.util.*;
public class ListSortingSearching {
public static void main(String[] args) {
// 创建测试数据
List<Integer> numbers = Arrays.asList(45, 12, 78, 23, 56, 89, 34, 67);
List<String> names = Arrays.asList("John", "Alice", "Bob", "Diana", "Charlie");
System.out.println("原始数字列表: " + numbers);
System.out.println("原始名字列表: " + names);
// 自然排序
Collections.sort(numbers);
Collections.sort(names);
System.out.println("\n自然排序后:");
System.out.println("数字: " + numbers);
System.out.println("名字: " + names);
// 自定义排序 - 降序
numbers.sort(Collections.reverseOrder());
names.sort(Collections.reverseOrder());
System.out.println("\n降序排序后:");
System.out.println("数字: " + numbers);
System.out.println("名字: " + names);
// 自定义比较器
names.sort((s1, s2) -> Integer.compare(s1.length(), s2.length()));
System.out.println("\n按长度排序: " + names);
// 二分查找
Collections.sort(numbers); // 二分查找需要先排序
int index = Collections.binarySearch(numbers, 56);
System.out.println("\n二分查找56的位置: " + index);
// 查找最大最小值
System.out.println("最大值: " + Collections.max(numbers));
System.out.println("最小值: " + Collections.min(numbers));
// 复杂对象排序
List<Student> students = Arrays.asList(
new Student("Alice", 85),
new Student("Bob", 92),
new Student("Charlie", 78),
new Student("Diana", 95)
);
System.out.println("\n原始学生列表: " + students);
students.sort(Comparator.comparing(Student::getScore).reversed());
System.out.println("按成绩降序: " + students);
students.sort(Comparator.comparing(Student::getName));
System.out.println("按姓名排序: " + students);
}
static class Student {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() { return name; }
public int getScore() { return score; }
@Override
public String toString() {
return name + "(" + score + ")";
}
}
}
3.3 不可变List和线程安全
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadSafeListDemo {
public static void main(String[] args) throws InterruptedException {
System.out.println("=== 不可变List演示 ===");
// 创建不可变List的几种方式
List<String> immutableList1 = List.of("A", "B", "C");
List<String> immutableList2 = Arrays.asList("X", "Y", "Z");
List<String> immutableList3 = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("1", "2", "3")));
System.out.println("不可变List1: " + immutableList1);
System.out.println("不可变List2: " + immutableList2);
System.out.println("不可变List3: " + immutableList3);
// 尝试修改会抛出异常
try {
immutableList1.add("D"); // 抛出UnsupportedOperationException
} catch (Exception e) {
System.out.println("修改不可变List抛出异常: " + e.getClass().getSimpleName());
}
System.out.println("\n=== 线程安全List演示 ===");
// 1. 使用Collections.synchronizedList
List<Integer> syncList = Collections.synchronizedList(new ArrayList<>());
// 2. 使用CopyOnWriteArrayList
CopyOnWriteArrayList<Integer> copyOnWriteList = new CopyOnWriteArrayList<>();
// 多线程测试
testThreadSafety(syncList, "synchronizedList");
testThreadSafety(copyOnWriteList, "CopyOnWriteArrayList");
}
private static void testThreadSafety(List<Integer> list, String listType) throws InterruptedException {
System.out.println("\n测试 " + listType + " 的线程安全性:");
ExecutorService executor = Executors.newFixedThreadPool(10);
// 创建多个写入任务
List<Runnable> writeTasks = new ArrayList<>();
for (int i = 0; i < 5; i++) {
final int taskId = i;
writeTasks.add(() -> {
for (int j = 0; j < 100; j++) {
list.add(taskId * 100 + j);
}
});
}
// 创建读取任务
Runnable readTask = () -> {
for (int i = 0; i < 10; i++) {
try {
// 遍历列表
for (Integer value : list) {
// 模拟读取操作
}
Thread.sleep(1);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
// 提交任务
long startTime = System.currentTimeMillis();
for (Runnable task : writeTasks) {
executor.submit(task);
}
for (int i = 0; i < 5; i++) {
executor.submit(readTask);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
long endTime = System.currentTimeMillis();
System.out.println(listType + " 最终大小: " + list.size());
System.out.println(listType + " 操作耗时: " + (endTime - startTime) + "ms");
}
}
四、性能分析和最佳实践
4.1 性能比较
import java.util.*;
public class ListPerformanceComparison {
private static final int ELEMENT_COUNT = 100000;
public static void main(String[] args) {
System.out.println("=== List实现类性能比较 ===");
System.out.println("测试元素数量: " + ELEMENT_COUNT);
// ArrayList性能测试
testArrayList();
// LinkedList性能测试
testLinkedList();
// Vector性能测试
testVector();
}
private static void testArrayList() {
System.out.println("\n--- ArrayList性能测试 ---");
ArrayList<Integer> arrayList = new ArrayList<>();
// 添加性能
long startTime = System.currentTimeMillis();
for (int i = 0; i < ELEMENT_COUNT; i++) {
arrayList.add(i);
}
long endTime = System.currentTimeMillis();
System.out.println("添加元素耗时: " + (endTime - startTime) + "ms");
// 随机访问性能
startTime = System.currentTimeMillis();
for (int i = 0; i < ELEMENT_COUNT; i++) {
arrayList.get(i);
}
endTime = System.currentTimeMillis();
System.out.println("随机访问耗时: " + (endTime - startTime) + "ms");
// 中间插入性能
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
arrayList.add(ELEMENT_COUNT / 2, i);
}
endTime = System.currentTimeMillis();
System.out.println("中间插入耗时: " + (endTime - startTime) + "ms");
// 删除性能
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
arrayList.remove(arrayList.size() / 2);
}
endTime = System.currentTimeMillis();
System.out.println("中间删除耗时: " + (endTime - startTime) + "ms");
}
private static void testLinkedList() {
System.out.println("\n--- LinkedList性能测试 ---");
LinkedList<Integer> linkedList = new LinkedList<>();
// 添加性能
long startTime = System.currentTimeMillis();
for (int i = 0; i < ELEMENT_COUNT; i++) {
linkedList.add(i);
}
long endTime = System.currentTimeMillis();
System.out.println("添加元素耗时: " + (endTime - startTime) + "ms");
// 顺序访问性能
startTime = System.currentTimeMillis();
for (int i = 0; i < ELEMENT_COUNT; i++) {
linkedList.get(i);
}
endTime = System.currentTimeMillis();
System.out.println("顺序访问耗时: " + (endTime - startTime) + "ms");
// 中间插入性能
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
linkedList.add(ELEMENT_COUNT / 2, i);
}
endTime = System.currentTimeMillis();
System.out.println("中间插入耗时: " + (endTime - startTime) + "ms");
// 删除性能
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
linkedList.remove(linkedList.size() / 2);
}
endTime = System.currentTimeMillis();
System.out.println("中间删除耗时: " + (endTime - startTime) + "ms");
}
private static void testVector() {
System.out.println("\n--- Vector性能测试 ---");
Vector<Integer> vector = new Vector<>();
// 添加性能
long startTime = System.currentTimeMillis();
for (int i = 0; i < ELEMENT_COUNT; i++) {
vector.add(i);
}
long endTime = System.currentTimeMillis();
System.out.println("添加元素耗时: " + (endTime - startTime) + "ms");
// 随机访问性能
startTime = System.currentTimeMillis();
for (int i = 0; i < ELEMENT_COUNT; i++) {
vector.get(i);
}
endTime = System.currentTimeMillis();
System.out.println("随机访问耗时: " + (endTime - startTime) + "ms");
}
}
4.2 最佳实践和常见陷阱
import java.util.*;
public class ListBestPractices {
public static void main(String[] args) {
System.out.println("=== List最佳实践和常见陷阱 ===");
// 1. 初始化时指定容量
List<String> listWithCapacity = new ArrayList<>(1000);
System.out.println("1. 初始化时指定容量可避免频繁扩容");
// 2. 使用接口类型声明
List<String> interfaceList = new ArrayList<>(); // 推荐
ArrayList<String> concreteList = new ArrayList<>(); // 不推荐
System.out.println("2. 使用List接口声明,提高代码灵活性");
// 3. 避免在循环中调用size()
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
numbers.add(i);
}
// 不推荐
long startTime = System.nanoTime();
for (int i = 0; i < numbers.size(); i++) {
// 每次循环都调用size()
}
long endTime = System.nanoTime();
System.out.println("3. 循环中调用size()耗时: " + (endTime - startTime) + "ns");
// 推荐
startTime = System.nanoTime();
int size = numbers.size();
for (int i = 0; i < size; i++) {
// 预先获取size
}
endTime = System.nanoTime();
System.out.println(" 预先获取size耗时: " + (endTime - startTime) + "ns");
// 4. 正确使用contains和indexOf
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange", "Grape");
System.out.println("4. contains检查: " + fruits.contains("Apple"));
System.out.println(" indexOf位置: " + fruits.indexOf("Orange"));
// 5. 批量操作优于单个操作
List<Integer> source = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> target = new ArrayList<>();
// 不推荐
for (Integer num : source) {
target.add(num);
}
// 推荐
target.addAll(source);
System.out.println("5. 使用addAll进行批量操作");
// 6. 注意subList的视图特性
List<Integer> original = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
List<Integer> subList = original.subList(1, 4);
System.out.println("6. 原始列表: " + original);
System.out.println(" 子列表: " + subList);
subList.set(0, 99); // 修改子列表会影响原始列表
System.out.println(" 修改子列表后原始列表: " + original);
// 7. 使用合适的实现类
demonstrateImplementationChoice();
}
private static void demonstrateImplementationChoice() {
System.out.println("\n7. 根据场景选择合适的实现类:");
// 场景1: 频繁随机访问
System.out.println("场景1 - 频繁随机访问: 选择ArrayList");
List<String> randomAccessList = new ArrayList<>();
// 场景2: 频繁插入删除
System.out.println("场景2 - 频繁插入删除: 选择LinkedList");
List<String> frequentModificationList = new LinkedList<>();
// 场景3: 多线程环境
System.out.println("场景3 - 多线程环境: 选择CopyOnWriteArrayList或Collections.synchronizedList");
List<String> threadSafeList = Collections.synchronizedList(new ArrayList<>());
// 场景4: 只读操作
System.out.println("场景4 - 只读操作: 使用不可变List");
List<String> immutableList = List.of("A", "B", "C");
}
}
五、实际应用案例
5.1 数据分页实现
import java.util.*;
public class ListPaginationExample {
public static void main(String[] args) {
// 模拟数据库数据
List<User> allUsers = generateUsers(145);
System.out.println("总用户数: " + allUsers.size());
// 分页查询
int pageSize = 10;
int totalPages = (int) Math.ceil((double) allUsers.size() / pageSize);
for (int page = 1; page <= totalPages; page++) {
List<User> pageData = getPage(allUsers, page, pageSize);
System.out.println("\n第 " + page + " 页数据:");
pageData.forEach(System.out::println);
}
// 使用现成的分页工具
Pagination<User> pagination = new Pagination<>(allUsers, pageSize);
System.out.println("\n=== 使用分页工具 ===");
System.out.println("第2页数据: " + pagination.getPage(2));
System.out.println("总页数: " + pagination.getTotalPages());
}
// 分页方法
public static <T> List<T> getPage(List<T> sourceList, int page, int pageSize) {
if (page <= 0 || pageSize <= 0) {
throw new IllegalArgumentException("页码和页大小必须大于0");
}
int fromIndex = (page - 1) * pageSize;
if (fromIndex >= sourceList.size()) {
return Collections.emptyList();
}
int toIndex = Math.min(fromIndex + pageSize, sourceList.size());
return sourceList.subList(fromIndex, toIndex);
}
// 生成测试用户数据
private static List<User> generateUsers(int count) {
List<User> users = new ArrayList<>();
Random random = new Random();
String[] firstNames = {"张", "李", "王", "赵", "陈", "刘", "杨", "黄", "周", "吴"};
String[] lastNames = {"伟", "芳", "娜", "秀英", "敏", "静", "丽", "强", "磊", "军"};
for (int i = 1; i <= count; i++) {
String name = firstNames[random.nextInt(firstNames.length)] +
lastNames[random.nextInt(lastNames.length)];
int age = 18 + random.nextInt(50);
users.add(new User(i, name, age));
}
return users;
}
// 分页工具类
static class Pagination<T> {
private final List<T> data;
private final int pageSize;
private final int totalPages;
public Pagination(List<T> data, int pageSize) {
this.data = new ArrayList<>(data);
this.pageSize = pageSize;
this.totalPages = (int) Math.ceil((double) data.size() / pageSize);
}
public List<T> getPage(int page) {
return getPage(data, page, pageSize);
}
public int getTotalPages() {
return totalPages;
}
public int getPageSize() {
return pageSize;
}
}
static class User {
private int id;
private String name;
private int age;
public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return String.format("User{id=%d, name='%s', age=%d}", id, name, age);
}
}
}
5.2 购物车实现
import java.util.*;
public class ShoppingCartExample {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 添加商品
cart.addItem(new Product(1, "iPhone 14", 5999.00), 1);
cart.addItem(new Product(2, "AirPods Pro", 1899.00), 2);
cart.addItem(new Product(3, "MacBook Pro", 12999.00), 1);
// 显示购物车
cart.displayCart();
// 更新数量
cart.updateQuantity(1, 2);
System.out.println("\n更新数量后:");
cart.displayCart();
// 删除商品
cart.removeItem(2);
System.out.println("\n删除商品后:");
cart.displayCart();
// 清空购物车
cart.clear();
System.out.println("\n清空购物车后:");
cart.displayCart();
}
static class ShoppingCart {
private List<CartItem> items;
public ShoppingCart() {
this.items = new ArrayList<>();
}
// 添加商品
public void addItem(Product product, int quantity) {
// 检查是否已存在
for (CartItem item : items) {
if (item.getProduct().getId() == product.getId()) {
item.setQuantity(item.getQuantity() + quantity);
return;
}
}
// 新商品
items.add(new CartItem(product, quantity));
}
// 删除商品
public void removeItem(int productId) {
items.removeIf(item -> item.getProduct().getId() == productId);
}
// 更新数量
public void updateQuantity(int productId, int quantity) {
for (CartItem item : items) {
if (item.getProduct().getId() == productId) {
if (quantity <= 0) {
removeItem(productId);
} else {
item.setQuantity(quantity);
}
return;
}
}
}
// 计算总价
public double getTotalPrice() {
return items.stream()
.mapToDouble(CartItem::getTotalPrice)
.sum();
}
// 清空购物车
public void clear() {
items.clear();
}
// 显示购物车
public void displayCart() {
if (items.isEmpty()) {
System.out.println("购物车为空");
return;
}
System.out.println("购物车内容:");
System.out.println("----------------------------------------");
System.out.printf("%-5s %-20s %-8s %-6s %-10s%n",
"ID", "商品名称", "单价", "数量", "小计");
System.out.println("----------------------------------------");
for (CartItem item : items) {
Product product = item.getProduct();
System.out.printf("%-5d %-20s %-8.2f %-6d %-10.2f%n",
product.getId(), product.getName(),
product.getPrice(), item.getQuantity(),
item.getTotalPrice());
}
System.out.println("----------------------------------------");
System.out.printf("总价: %.2f%n", getTotalPrice());
}
}
static class CartItem {
private Product product;
private int quantity;
public CartItem(Product product, int quantity) {
this.product = product;
this.quantity = quantity;
}
public double getTotalPrice() {
return product.getPrice() * quantity;
}
// getters and setters
public Product getProduct() { return product; }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
}
static class Product {
private int id;
private String name;
private double price;
public Product(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
// getters
public int getId() { return id; }
public String getName() { return name; }
public double getPrice() { return price; }
}
}
总结
- List的核心特性:有序性、可重复性、索引访问
- 主要实现类:ArrayList、LinkedList、Vector的特点和适用场景
- 高级用法:各种遍历方式、排序搜索、线程安全等
- 性能优化:不同操作的性能特点和最佳实践
- 实际应用:通过完整案例展示List在实际项目中的应用
- 大多数场景选择ArrayList
- 频繁插入删除选择LinkedList
- 多线程环境选择CopyOnWriteArrayList或同步包装
- 只读场景选择不可变List
