list.stream.forEach对下标数组 remove删除问题

Java Stream删除List元素陷阱
本文探讨了使用Java Stream API从List中删除元素时遇到的问题。由于Stream操作默认不会修改原始集合,直接在forEach循环中调用remove方法可能导致并发修改异常。文章提供了正确的解决方案,即通过调整索引值来避免这一问题。

今天遇到一个坑,因为list.stream只能对对象遍历,所以int也要放到Integer的集合里这样导致删除时,走的是对象删除:


public static void main(String[] args) {
        //要删除的下标集合
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(2);

        //原集合
        List<String> stringList = new ArrayList<>();
        stringList.add("张三");
        stringList.add("李四");
        stringList.add("王五");
        stringList.add("马六");
        stringList.add("赵七");
        stringList.add("刘八");
        stringList.add("张三2");

        list.stream().forEach(index->{
            //删除指定下标
            stringList.remove(index);
        });

        stringList.stream().forEach(s -> System.out.println(s));
    }

大家看下打印结果:
在这里插入图片描述 stringList.remove(index);//没有起作用

换成这样就可以了:public static void main(String[] args) {
        //要删除的下标集合
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(2);

        //原集合
        List<String> stringList = new ArrayList<>();
        stringList.add("张三");
        stringList.add("李四");
        stringList.add("王五");
        stringList.add("马六");
        stringList.add("赵七");
        stringList.add("刘八");
        stringList.add("张三2");

        list.stream().forEach(index->{
            //删除指定下标
            stringList.remove(index+0);//看这里
        });

        stringList.stream().forEach(s -> System.out.println(s));
    }

在这里插入图片描述
主要原因就是一个对象删除一个是下标删除,不把Integer转成int走的是对象删除:
在这里插入图片描述

<think>我们被要求回答如何遍历ArrayList,并且参考了之前提供的引用内容。根据引用,有多种遍历ArrayList的方法,包括使用Iterator、for-each循环、转换为数组遍历、使用listIterator以及Java 8的forEachRemaining等。我们将结合这些内容给出全面的遍历方法。 注意:用户的问题是关于遍历ArrayList,而不是将List存入数组(虽然遍历中可能用到数组转换)。因此,我们需要专注于遍历方法。 根据引用[1][2][3][4][5],我们可以总结以下几种遍历方法: 1. 使用Iterator迭代器 2. 使用for-each循环(增强for循环) 3. 使用普通的for循环(通过下标访问) 4. 使用ListIterator(可以双向遍历,但引用中提到只应该由后向前遍历ArrayList?实际上,我们通常用它来双向遍历,但ArrayList中向前遍历效率不高?注意引用[3]说明:ListIterator只应该用来由后向前遍历ArrayList,而不是用来插入和删除元素,因为这比LinkedList开销要大很多。所以,我们这里只展示遍历,不进行插入删除) 5. 使用Java 8的forEach方法(引用[2]中提到了forEachRemaining,实际上还有直接使用forEach方法) 6. 转换为数组后遍历(引用[2]中第二种方法) 另外,引用[5]还提到了使用Arrays工具类打印数组,但这主要用于数组,我们可以借鉴。 我们将逐一介绍这些方法,并给出代码示例。 注意:我们创建一个ArrayList作为示例,然后使用各种方法遍历。 完整代码示例: </think>### Java中遍历ArrayList的7种方法 #### 1. for循环(索引访问) ```java ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); for(int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); // 通过索引直接访问元素 } ``` - **特点**:通过索引随机访问元素,适合需要修改元素的场景[^4] #### 2. 增强for循环(foreach) ```java for(String item : list) { System.out.println(item); // 简洁易读 } ``` - **特点**:语法简洁,适用于只读遍历(禁止修改元素)[^2] #### 3. Iterator迭代器 ```java Iterator<String> it = list.iterator(); while(it.hasNext()) { System.out.println(it.next()); // it.remove(); // 可安全删除当前元素 } ``` - **特点**:支持安全的元素删除操作,通用性强[^1] #### 4. ListIterator双向遍历 ```java ListIterator<String> lit = list.listIterator(); // 正向遍历 while(lit.hasNext()) { System.out.println(lit.next()); } // 反向遍历 while(lit.hasPrevious()) { System.out.println(lit.previous()); } ``` - **特点**:支持双向遍历和修改操作,但效率低于单向迭代器[^3] #### 5. forEach + Lambda(Java 8+) ```java list.forEach(item -> System.out.println(item)); // 或方法引用 list.forEach(System.out::println); ``` - **特点**:函数式编程风格,代码最简洁[^2] #### 6. toArray()转换后遍历 ```java Object[] array = list.toArray(); for(Object obj : array) { System.out.println(obj); } ``` - **特点**:将列表转为数组后操作,适合需复用数组的场景[^2] #### 7. Stream API(Java 8+) ```java list.stream().forEach(System.out::println); // 带过滤操作 list.stream() .filter(s -> s.startsWith("A")) .forEach(System.out::println); ``` - **特点**:支持链式操作和并行处理[^5] ### 完整示例代码 ```java import java.util.*; public class ArrayListTraversal { public static void main(String[] args) { // 创建ArrayList ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "Apple", "Banana", "Cherry"); // 1. for循环遍历 System.out.println("=== 1. for循环 ==="); for(int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } // 2. 增强for循环 System.out.println("=== 2. 增强for循环 ==="); for(String item : list) { System.out.println(item); } // 3. Iterator遍历 System.out.println("=== 3. Iterator遍历 ==="); Iterator<String> it = list.iterator(); while(it.hasNext()) { System.out.println(it.next()); } // 4. forEach + Lambda System.out.println("=== 4. forEach Lambda ==="); list.forEach(System.out::println); // 5. Stream API System.out.println("=== 5. Stream API ==="); list.stream().forEach(System.out::println); } } ``` ### 遍历方式对比 | 方法 | 随机访问 | 修改安全 | 简洁度 | 适用场景 | |--------------------|----------|----------|--------|------------------------------| | for循环 | ✔️ | ✔️ | ★★☆ | 需要索引操作/修改元素 | | 增强for循环 | ✘ | ✘ | ★★★ | 简单只读遍历 | | Iterator | ✘ | ✔️ | ★★☆ | 需要删除元素 | | ListIterator | ✘ | ✔️ | ★☆☆ | 双向遍历/插入删除 | | forEach(Lambda) | ✘ | ✘ | ★★★ | Java 8+的简洁遍历 | | Stream API | ✘ | ✘ | ★★☆ | 需要过滤/映射等流操作 | | toArray转换 | ✔️ | ✘ | ★★☆ | 需要数组操作的场景 | > **最佳实践**:推荐优先使用**增强for循环**(只读场景)或**forEach+Lambda**(Java 8+),需要修改元素时使用**Iterator**,需要索引操作时使用**for循环**[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值