Java集合遍历3大死亡陷阱!90%新手都中招(附逃生代码)
导语:
“你的程序突然抛出
ConcurrentModificationException?不是见鬼,是Java集合遍历的‘死亡陷阱’在索命!今日头条揭秘电商系统崩溃背后的集合操作黑幕,阿里P7急救代码曝光,文末送《集合安全手册》+调试工具包!”
一、死亡循环:foreach删除引发的血案
用户求救:
“遍历List删除元素时程序崩溃,日志显示神秘异常!”
致命代码:
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String s : list) {
if ("B".equals(s)) {
list.remove(s); // 抛出ConcurrentModificationException!
}
}
逃生方案:
// 正确方式1:迭代器删除
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if ("B".equals(it.next())) {
it.remove(); // 安全删除
}
}
// 正确方式2:removeIf一行搞定
list.removeIf(s -> "B".equals(s));
二、性能刺客:嵌套循环毁掉CPU
灾难场景:
List<User> users = get10万用户();
List<Order> orders = get100万订单();
// 双重循环:时间复杂度O(n^2)
for (User user : users) {
for (Order order : orders) {
if (order.getUserId().equals(user.getId())) {
// 业务处理
}
}
}
后果:
- 10万用户 × 100万订单 = 1000亿次比较
- CPU占用100%持续2小时 → 服务器熔断
优化代码:
Map<String, List<Order>> orderMap = orders.stream()
.collect(Collectors.groupingBy(Order::getUserId));
for (User user : users) {
List<Order> userOrders = orderMap.getOrDefault(user.getId(), emptyList());
// 时间复杂度降为O(n)
}
三、内存黑洞:未设初始容量的ArrayList
错误示范:
List<byte[]> list = new ArrayList<>(); // 默认容量10
for (int i=0; i<100_000; i++) {
list.add(new byte[1024]); // 触发15次扩容复制!
}
扩容代价:
操作次数 | 扩容后容量 | 拷贝数据量 |
1 | 10 → 15 | 10KB |
10 | 15 → 22 | 15KB |
15 | 22 → 33 | 22KB |
总计:100万元素扩容18次 → 拷贝数据量超1GB |
正确代码:
List<byte[]> list = new ArrayList<>(100_000); // 预分配容量
四、福利时间
“私信发送‘集合’免费领:
- 《Java集合框架源码解析》
- 高频面试题答案库(含大厂真题)
- 阿里内部《性能压测报告模板》
下期预告:
《Java并发编程:从ThreadLocal内存泄漏到百万QPS架构设计!》点击关注,进阶架构师!