繁体   English   中英

Java ArrayList.set() 方法在 forEach 循环中的意外行为

[英]Unexpected behavior of Java ArrayList.set() method with multiplication in forEach loop

设置初始数组值(没问题):

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]

尝试forEach添加(没问题):

numbers.forEach(number -> {
    numbers.set(numbers.indexOf(number), number + 10);
});
System.out.println(numbers.toString());

控制台输出:[13、11、14、12]

尝试forEach乘法:

numbers.forEach(number -> {
    numbers.set(numbers.indexOf(number), number * 2);
});
System.out.println(numbers.toString());

控制台输出:[6, 4 , 8, 2 ]

我的问题是,为什么乘法循环后的数组在索引 1 处具有值 4,在索引 3 处具有值 2? 它们不应该分别是 1 * 2 = 2 和 2 * 2 = 4 吗?

我尝试了上面的代码,并期望在 forEach 乘法之后得到一个值为 [6, 2, 8, 4] 的数组。 相反,我得到了 [6, 4 , 8, 2 ]。

indexOf返回值第一次出现的索引。 让我们遍历循环,看看发生了什么。

  1. 我们从 [3, 1, 4, 2] 开始
  2. 第一个元素是 3。它的索引是 0,所以我们得到 [6, 1, 4, 2]
  3. 第二个元素是1,它的索引是1,所以我们得到[6, 2, 4, 2]
  4. 第三个元素是4,它的索引是2,所以我们得到[6, 2, 8, 2]
  5. 第四个元素是 2,它的第一个索引是 1,所以我们得到 [6, 4, 8, 2]

这不仅是错误的(如您所见),还意味着对于每次迭代,您都需要在整个列表(使用indexOf )中搜索一个您应该已经知道它在哪里的值。

使用一个好的旧for循环会更适合这里:

for (int i = 0; i < numbers.size(); ++i) {
    numbers.set(i, numbers.get(i) * 2);
}

您在乘法期间得到不正确的结果,因为在处理最后一个元素时,列表看起来像这样[6, 2, 8, 2] (索引1处的元素已更改为2 )。 因此, indexOf()返回1 ,而不是3 (正如您可能预期的那样)。

在这种情况下,当您需要替换列表中的每个元素时,您可以使用 Java 8 方法List.replaceAll()这要方便得多,因为您不需要使用索引拨号:

numbers.replaceAll(number -> number * 2);

System.out.println(numbers);

输出:

[6, 2, 8, 4]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM