当前位置: 首页 > news >正文

# Java List完全指南:从入门到高阶应用

一、List接口:有序集合的核心

作为Java集合框架中最常用的接口之一,List代表了有序可重复的元素序列。与Set的无序唯一特性形成鲜明对比,List更像是我们日常生活中的排队场景——先来后到很重要,且允许相同元素存在。

1.1 List核心特性

  • 有序性:元素按插入顺序存储(非排序顺序)
  • 可重复:允许存储相同元素的多个实例
  • 索引访问:支持基于下标的高效随机访问
  • 丰富API:提供位置相关的操作方法

1.2 List主要实现类对比

实现类数据结构线程安全随机访问效率增删效率适用场景
ArrayList动态数组不安全O(1)O(n)查询多、增删少的场景
LinkedList双向链表不安全O(n)O(1)频繁插入删除的场景
Vector动态数组安全O(1)O(n)需要线程安全的场景(已逐渐被淘汰)
CopyOnWriteArrayList动态数组安全O(1)O(n)读多写少的并发场景

二、基础操作实战

2.1 创建与初始化

// 最常用的初始化方式(Java 7+)
List<String> arrayList = new ArrayList<>(); // 使用Arrays工具类快速初始化
List<Integer> numbers = Arrays.asList(1, 2, 3); // Java 9+ 的工厂方法
List<String> immutableList = List.of("A", "B", "C");// 指定初始容量(优化技巧)
List<Object> optimizedList = new ArrayList<>(100);

2.2 增删改查四连击

List<String> fruits = new ArrayList<>();// 增(尾部添加)
fruits.add("Apple");  
fruits.add(0, "Banana"); // 指定位置插入// 删
fruits.remove("Apple");  // 按元素删除
fruits.remove(0);        // 按索引删除// 改
fruits.set(0, "Mango");  // 替换指定位置元素// 查
String first = fruits.get(0); // 获取元素
int index = fruits.indexOf("Mango"); // 查找位置
boolean exists = fruits.contains("Apple"); // 存在判断

2.3 遍历方式大比拼

// 1. 经典for循环(适合需要索引的场景)
for (int i = 0; i < fruits.size(); i++) {System.out.println(fruits.get(i));
}// 2. 增强for循环(简洁明了)
for (String fruit : fruits) {System.out.println(fruit);
}// 3. 迭代器(可安全删除元素)
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {String fruit = it.next();if (fruit.equals("Mango")) {it.remove(); // 安全删除}
}// 4. Java 8+ forEach + Lambda
fruits.forEach(fruit -> System.out.println(fruit));

三、进阶技巧与最佳实践

3.1 容量优化之道

ArrayList内部使用Object数组存储数据,默认初始容量为10。当元素数量达到当前容量时,会自动进行1.5倍扩容(int newCapacity = oldCapacity + (oldCapacity >> 1)),这个扩容操作会导致数组复制,影响性能。

优化建议

// 预估数据量较大时指定初始容量
List<BigData> bigList = new ArrayList<>(10000);// 已知最终大小时使用一次性扩容
ArrayList<String> optimized = new ArrayList<>();
optimized.ensureCapacity(5000); // 预先扩容

3.2 不可变列表的多种实现

// 1. Java 9+的不可变列表
List<String> immutable1 = List.of("A", "B", "C");// 2. Collections工具类
List<String> immutable2 = Collections.unmodifiableList(mutableList);// 3. Guava库的不可变列表
ImmutableList<String> immutable3 = ImmutableList.of("A", "B", "C");// 尝试修改将抛出UnsupportedOperationException
immutable1.add("D"); // 抛出异常

3.3 高效列表合并技巧

List<String> list1 = Arrays.asList("A", "B");
List<String> list2 = Arrays.asList("C", "D");// 方法1:使用addAll(会修改原集合)
List<String> merged = new ArrayList<>(list1);
merged.addAll(list2);// 方法2:Java 8 Stream API(不修改原集合)
List<String> merged2 = Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());// 方法3:Guava库的Iterables.concat
Iterable<String> merged3 = Iterables.concat(list1, list2);

四、性能陷阱与规避方案

4.1 随机访问的坑

LinkedList<String> linkedList = new LinkedList<>();
// 填充10000个元素...// 反模式:链表随机访问(效率O(n))
for (int i = 0; i < linkedList.size(); i++) {String item = linkedList.get(i); // 性能灾难!
}// 正确做法:使用迭代器
for (Iterator<String> it = linkedList.iterator(); it.hasNext(); ) {String item = it.next(); // 效率O(1)
}

4.2 并发修改异常

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));// 错误示例:遍历时修改
for (String s : list) {if (s.equals("B")) {list.remove(s); // 抛出ConcurrentModificationException}
}// 解决方案1:使用迭代器的remove方法
Iterator<String> it = list.iterator();
while (it.hasNext()) {if (it.next().equals("B")) {it.remove(); // 安全删除}
}// 解决方案2:Java 8+ removeIf
list.removeIf(s -> s.equals("B"));

五、实际应用案例

5.1 分页查询实现

public static <T> List<T> getPage(List<T> sourceList, int page, int pageSize) {if (sourceList == null || sourceList.isEmpty()) {return Collections.emptyList();}int totalItems = sourceList.size();int fromIndex = (page - 1) * pageSize;if (fromIndex >= totalItems) {return Collections.emptyList();}int toIndex = Math.min(fromIndex + pageSize, totalItems);return sourceList.subList(fromIndex, toIndex);
}// 使用示例
List<Integer> numbers = IntStream.range(0, 100).boxed().collect(Collectors.toList());List<Integer> page3 = getPage(numbers, 3, 10); // 获取第3页数据

5.2 列表排序大全

List<String> names = Arrays.asList("John", "Alice", "Bob");// 1. 自然排序
Collections.sort(names); // 原地修改
List<String> sorted = names.stream().sorted().toList(); // Java 16+// 2. 自定义比较器
names.sort(Comparator.comparing(String::length)); // 按长度排序// 3. 多条件排序
List<Person> people = getPeople();
people.sort(Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName));// 4. 逆序排列
names.sort(Comparator.reverseOrder());

六、与数组的转换技巧

// List → 数组
List<String> list = Arrays.asList("A", "B", "C");
String[] array1 = list.toArray(new String[0]); // 推荐方式
String[] array2 = list.toArray(String[]::new); // Java 11+// 数组 → List
String[] arr = {"X", "Y", "Z"};
List<String> fromArray1 = Arrays.asList(arr); // 固定大小列表
List<String> fromArray2 = new ArrayList<>(Arrays.asList(arr)); // 可变列表
List<String> fromArray3 = Stream.of(arr).collect(Collectors.toList()); // Java 8

总结与选择建议

  1. 默认选择:大多数情况下优先使用ArrayList,除非有频繁的插入删除操作
  2. 线程安全:考虑Collections.synchronizedListCopyOnWriteArrayList
  3. 性能敏感:预估大小并设置初始容量,避免频繁扩容
  4. 不可变需求:使用List.of()或不可变集合库
  5. 复杂操作:善用Stream API进行过滤/映射/归约等操作

记住:没有最好的实现,只有最适合场景的实现。理解每种List实现的内在机制,才能在实际开发中做出最优选择。

相关文章:

  • [面试]SoC验证工程师面试常见问题(五)TLM通信篇
  • Vue v-model 深度解析:实现原理与高级用法
  • uniapp-商城-48-后台 分类数据添加修改弹窗bug
  • 【含文档+源码】基于SpringBoot的新能源充电桩管理系统的设计与实现
  • 最小生成树
  • 《C++探幽:模板从初阶到进阶》
  • 【Rust】枚举和模式匹配
  • 计算机大类专业数据结构下半期实验练习题
  • 《用MATLAB玩转游戏开发:从零开始打造你的数字乐园》基础篇(2D图形交互)-俄罗斯方块:用旋转矩阵打造经典
  • python-django项目启动寻找静态页面html顺序
  • C++GO语言微服务之gorm框架操作MySQL
  • 无法更新Google Chrome的解决问题
  • [Pandas]数据处理
  • Dify使用总结
  • JVM对象创建内存分配
  • 初识Linux · 传输层协议TCP · 下
  • 推荐一款免费开源工程项目管理系统软件,根据工程项目全过程管理流程开发的OA 办公系统
  • 为什么tcp不能两次握手
  • PyTorch API 8 - 工具集、onnx、option、复数、DDP、量化、分布式 RPC、NeMo
  • ScaleTransition 是 Flutter 中的一个动画组件,用于实现缩放动画效果。
  • 深圳市政协原副主席王幼鹏被“双开”
  • 习近平会见古共中央第一书记、古巴国家主席迪亚斯-卡内尔
  • 中国一重集团有限公司副总经理陆文俊被查
  • 美乌基金协议:美国搞了一套可在资源富集地区复刻的商业模式
  • 商务部:中方愿同各国一道加强合作,促进跨境电商健康可持续发展
  • “救护车”转运病人半路加价,从宝鸡到西安往返都要多收钱