在Java中,如何在不使用for循环的情况下执行n个数组的元素级加法

在Java中,如何在不使用for循环的情况下执行n个数组的元素级加法,java,arrays,vectorization,Java,Arrays,Vectorization,正如标题所示,我想知道如何使用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[

正如标题所示,我想知道如何使用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);
}
对于只有20个数组来说,这当然是微不足道的,但是如果我们有1000000个数组,这可能会非常耗时。有更好的方法吗?我使用
arrays.setAll
函数有一种矢量化的方法,可以对两个数组按元素求和,但这可以泛化为将n个数组相加吗?请注意,不需要将数组列表存储为
ArrayList
,这正是我首先想到的

另外,如果有人想要一些示例数字,下面是我在浏览脚本时得到的:

[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]

如果有1000000个数组,您可能需要考虑使用
ArrayList
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;
}
输出


如果有1000000个数组,您可能需要考虑使用
ArrayList
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;
}
输出


无论如何,您都必须遍历所有数组。我会避免在这里使用闭包,因为它可能不是最优的(除非JIT编译器做得很好),但就算法复杂性而言,没有什么好处。如果您有1000000个数组,您可能会考虑使用
ArrayList
int[][]来节省内存
。无论如何,您都必须遍历所有数组。我会避免在这里使用闭包,因为它可能不是最优的(除非JIT编译器做得很好),但就算法复杂性而言,没有什么好处。如果您有1000000个数组,您可能会考虑使用
ArrayList
int[][]
来节省内存。嘿,非常有用的答案!那么,for循环确实是最有效的方法吗?@JamesL
Arrays.setAll()
也使用
for
循环。但速度较慢,因为它必须为每个值对Lambda表达式进行动态方法调用。JIT可能会消除这一点。或者不是但通常,如果性能非常关键,请远离流和Lambda表达式。它们对于代码的清晰性非常好,但可能会对性能产生影响。很高兴知道。我来自R的背景,在R中,尽全力避免for循环是一种很好的做法——我怀疑这种差异来自Java的编译而非动态。@JamesL我不知道R,但网站上说“R是一种用于统计计算和图形的语言和环境”,因此,计算统计数据和构建图像像素似乎需要大量的数字运算,因此需要并行计算,这很容易通过函数计算实现。
for
循环不能自动并行化,但流可以并行化,
setAll
有一个
parallelSetAll
变量,这就是为什么需要Lambda。lambda可能会慢一些,但如果你向它扔16个以上的CPU,结果肯定会快得多。“我们还可以保持上半场,即使有这样的保证”-在不满足保证的情况下默默地继续是不健康的防御编程。代码通常应该在这种情况下抛出。嘿,真的很有用的答案!那么,for循环确实是最有效的方法吗?@JamesL
Arrays.setAll()
也使用
for
循环。但速度较慢,因为它必须为每个值对Lambda表达式进行动态方法调用。JIT可能会消除这一点。或者不是但通常,如果性能非常关键,请远离流和Lambda表达式。它们对于代码的清晰性非常好,但可能会对性能产生影响。很高兴知道。我来自R的背景,在R中,尽全力避免for循环是一种很好的做法——我怀疑这种差异来自Java的编译而非动态。@JamesL我不知道R,但网站上说“R是一种用于统计计算和图形的语言和环境”,因此,计算统计数据和构建图像像素似乎需要大量的数字运算,因此需要并行计算,这很容易通过函数计算实现。
for
循环不能自动并行化,但流可以并行化,
setAll
有一个
parallelSetAll
变量,这就是为什么需要Lambda。lambda可能会慢一些,但如果你向它扔16个以上的CPU,结果肯定会快得多。“我们还可以保持上半场,即使有这样的保证”-在不满足保证的情况下默默地继续是不健康的防御编程。在这种情况下,代码通常应该抛出。
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]