如何在 Java 中不简单地使用 for 循环来执行 element-wise 添加 n 个数组

How to perform element-wise addition of n arrays without simply using a for loop in Java

如标题所示,我想知道如何使用 Java 求和 n(其中 n 是任意的大于 2) 的数组一起,以一种随着 n 增加而缩放的方式。

用一个例子来解释可能是最容易的。我使用以下代码生成了 20 个长度为 5 的数组。

int n = 20;
int k = 5;

Random rand = new Random();
ArrayList<Integer[]> tuplesList = new ArrayList<>();

for (int i = 0; i < n; i++) {
    Integer[] tuple = new Integer[k];
    Arrays.setAll(tuple, index -> rand.nextInt(30));
    tuplesList.set(i, tuple);
}

说到这里我希望可以改进。我当前将数组相加的方法 element-wise 包括简单地遍历每个数组并将它们的元素添加到累积和中。

int[] cumSum = new int[k];

for (Integer[] tup : tuplesList) {
    Arrays.setAll(cumSum, ind -> cumSum[ind] + tup[ind]);
}

System.out.println(Arrays.toString(cumSum));

这对于只有 20 个数组来说当然是微不足道的,但如果我们有 1,000,000 个数组,这可能会很漂亮 time-consuming。有一个更好的方法吗?我有一种使用 Arrays.setAll 函数对两个数组 element-wise 求和的矢量化方法,但这是否可以泛化为将 n 数组加在一起?请注意,没有要求数组列表不必存储为 ArrayList<Integer[]>,这正是我首先想到的地方。

P.S。如果有人想要一些示例数字,这是我 运行 通过我的脚本时得到的:

[12, 20, 12, 22, 14]
[1, 10, 23, 9, 27]
[3, 2, 17, 24, 11]
[6, 11, 22, 5, 15]
[7, 26, 28, 27, 8]
[10, 23, 2, 15, 7]
[13, 5, 19, 3, 9]
[21, 23, 17, 16, 24]
[4, 20, 6, 14, 14]
[19, 4, 16, 24, 4]
[27, 14, 28, 0, 17]
[27, 20, 3, 8, 29]
[2, 21, 0, 24, 26]
[3, 2, 1, 23, 23]
[11, 11, 15, 26, 17]
[10, 26, 10, 8, 3]
[3, 27, 11, 13, 28]
[1, 29, 26, 3, 14]
[20, 1, 10, 29, 8]
[11, 25, 29, 28, 5]

Output:
[211, 320, 295, 321, 303]

如果您有 1,000,000 个数组,您可能需要考虑使用 ArrayList<int[]>int[][].

来节省内存

如果您确实更改为 int[][],绝对最有效的方法是这样的:

static int[] sum(int[]... input) {
    int maxLen = 0;
    for (int[] arr : input)
        if (arr.length > maxLen)
            maxLen = arr.length;
    int[] sum = new int[maxLen];
    for (int[] arr : input)
        for (int i = 0; i < arr.length; i++)
            sum[i] += arr[i];
    return sum;
}

前半部分当然可以换成maxLen = input[0].length如果绝对保证所有数组等长。由于与代码的后半部分相比,该代码对性能的影响很小,因此我们不妨保留前半部分,即使有这样的保证(defensive programming)。

测试

System.out.println(Arrays.toString(sum(
        new int[] { 12, 20, 12, 22, 14 },
        new int[] { 1, 10, 23, 9, 27 },
        new int[] { 3, 2, 17, 24, 11 },
        new int[] { 6, 11, 22, 5, 15 },
        new int[] { 7, 26, 28, 27, 8 },
        new int[] { 10, 23, 2, 15, 7 },
        new int[] { 13, 5, 19, 3, 9 },
        new int[] { 21, 23, 17, 16, 24 },
        new int[] { 4, 20, 6, 14, 14 },
        new int[] { 19, 4, 16, 24, 4 },
        new int[] { 27, 14, 28, 0, 17 },
        new int[] { 27, 20, 3, 8, 29 },
        new int[] { 2, 21, 0, 24, 26 },
        new int[] { 3, 2, 1, 23, 23 },
        new int[] { 11, 11, 15, 26, 17 },
        new int[] { 10, 26, 10, 8, 3 },
        new int[] { 3, 27, 11, 13, 28 },
        new int[] { 1, 29, 26, 3, 14 },
        new int[] { 20, 1, 10, 29, 8 },
        new int[] { 11, 25, 29, 28, 5 }
)));

输出

[211, 320, 295, 321, 303]