You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java ArrayList.set()在forEach循环中乘法操作的异常行为疑问

问题分析:ArrayList forEach中使用indexOf导致的元素修改异常

问题重现

初始化数组

import java.util.ArrayList;
public class arraylists {

    public static void main (String[] args) {
        ArrayList<Integer> numbers = new ArrayList<Integer>();
        numbers.add(3);
        numbers.add(1);
        numbers.add(4);
        numbers.add(2);
        System.out.println(numbers.toString()); // 输出:[3, 1, 4, 2]
    }
}

加法操作(结果符合预期)

numbers.forEach(number -> {
    numbers.set(numbers.indexOf(number), number + 10);
});
System.out.println(numbers.toString()); // 输出:[13, 11, 14, 12]

乘法操作(结果异常)

numbers.forEach(number -> {
    numbers.set(numbers.indexOf(number), number * 2);
});
System.out.println(numbers.toString()); // 实际输出:[6, 4, 8, 2],预期输出:[6, 2, 8, 4]

问题根源

问题出在numbers.indexOf(number)的逻辑上:

  • indexOf()的作用是返回数组中第一个与目标元素相等的索引,并非当前遍历到的元素的索引。
  • 乘法操作的执行步骤拆解:
    1. 遍历第一个元素3:indexOf(3)找到索引0,设置为3*2=6,数组变为[6,1,4,2]
    2. 遍历第二个元素1:indexOf(1)找到索引1,设置为1*2=2,数组变为[6,2,4,2]
    3. 遍历第三个元素4:indexOf(4)找到索引2,设置为4*2=8,数组变为[6,2,8,2]
    4. 遍历第四个元素2:此时数组中第一个2位于索引1,indexOf(2)返回1,于是把索引1的元素修改为2*2=4,最终数组变成[6,4,8,2]

加法操作未出现异常,是因为每个元素加10后都是唯一值,indexOf()总能匹配到当前元素对应的正确索引,不会出现“找错位置”的情况。

解决方案

要避免这类问题,需要直接基于索引遍历,或使用不依赖元素值定位的修改方式:

方案1:普通for循环按索引遍历

for (int i = 0; i < numbers.size(); i++) {
    numbers.set(i, numbers.get(i) * 2);
}
System.out.println(numbers.toString()); // 输出:[6,2,8,4]

方案2:使用ListIterator(支持遍历中安全修改)

ListIterator<Integer> iterator = numbers.listIterator();
while (iterator.hasNext()) {
    iterator.set(iterator.next() * 2);
}
System.out.println(numbers.toString()); // 输出:[6,2,8,4]

方案3:使用ArrayList的replaceAll方法(最简洁)

numbers.replaceAll(number -> number * 2);
System.out.println(numbers.toString()); // 输出:[6,2,8,4]

内容的提问来源于stack exchange,提问作者Sean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:05:23