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

# 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实现的内在机制,才能在实际开发中做出最优选择。

http://www.xdnf.cn/news/5232.html

相关文章:

  • 栈应用:辅助站(c++)
  • C#异步Task,await,async和Unity同步协程
  • 玩转Docker | 使用Docker部署Note Mark笔记应用程序
  • [架构之美]Spring Boot集成MyBatis-Plus高效开发(十七)
  • 求两个正整数的最大公约数和最小公倍数:方法1:辗转相除法
  • 01 | 大模型微调 | 从0学习到实战微调 | AI发展与模型技术介绍
  • STM32实现九轴IMU的卡尔曼滤波
  • 如何在postman使用时间戳
  • Windows下的临界写法
  • 回文数(9)
  • 气象大模型光伏功率预测中的应用:从短期,超短期,中长期的实现与开源代码详解
  • C++GO语言微服务之图片、短信验证码生成及存储
  • 【沉浸式求职学习day35】【Tomcat安装、配置】【Http简述】
  • Linux指令入门:DevOps与SRE视角
  • SDC命令详解:使用all_outputs命令进行查询
  • 轻松制作高质量视频,实时生成神器LTX-Video重磅登场!
  • 睿思量化小程序
  • LeetCode 88. 合并两个有序数组 | Python 最简写法 + 实战注释
  • Java面向对象
  • bcm5482 phy 场景总结
  • 技嘉主板BIOS升级
  • 树 Part 4
  • D. Apple Tree Traversing 【Codeforces Round 1023 (Div. 2)】
  • NX949NX952美光科技闪存NX961NX964
  • 短剧 CPS 分销系统开发搭建,开启流量变现新征程
  • 数字签名与证书
  • 北斗终端设备应用
  • 【含文档+源码】基于SpringBoot的新能源充电桩管理系统的设计与实现
  • ODA服务器计算节点本地硬盘状态异常的处理
  • 【金仓数据库征文】国产数据库KingbaseES安装与使用详解