当前位置: 首页 > 知识库问答 >
问题:

在2d阵列中循环。性能问题[关闭]

司徒光霁
2023-03-14

编辑问题以包括所需的行为、特定的问题或错误,以及重现问题所需的最短代码。这将帮助其他人回答这个问题。

为什么下面未注释的代码比注释掉的代码快得多?让我们在这里初学者,老实说,我看不出两者之间的区别。

class Solution {
    //public int maximumWealth(int[][] accounts) {
    //    int max = 0;
    //    for (int i = 0; i < accounts.length; i++) {
    //        int sum = 0;
    //        for (int j = 0; j < accounts[i].length; j++) {
    //            sum += accounts[i][j];
    //        }
    //        max = Integer.max(max, sum);
    //    }
    //    return max;
    //}
    public int maximumWealth(int[][] accounts) {
        int max = 0;
        for (int[] account : accounts) {
            int sum = 0;
            for (int j = 0; j < account.length; j++) {
                sum += account[j];
            }
            max = Integer.max(max, sum);
        }
        return max;
    }
}

共有2个答案

上官波鸿
2023-03-14

取一个包含30000x30000个随机元素的二维数组。准备三种基准测试方法,每种方法调用20次,测量时间并计算平均值。

结果:增强的for循环比常规for循环快,并行流快两倍。

   enhanced for: avg 750 ms
       for loop: avg 1013 ms
parallel stream: avg 385 ms

最佳结果:平行流

public static int maximumWealthPStream(int[][] accounts) {
    return Arrays.stream(accounts).parallel()
            .mapToInt(arr -> Arrays.stream(arr).sum())
            .max().orElse(0);
}

完整结果:

   enhanced for: 1281 | 1286 |  701 |  710 |  690 |  691 |  702 |  688 |  689 |  676 |  673 |  705 |  698 |  686 |  686 |  688 |  684 |  683 |  690 |  696 || avg 750 ms
       for loop:  669 |  667 | 1252 |  677 |  670 |  659 |  669 |  652 |  657 | 1226 | 1240 | 1244 | 1279 | 1230 | 1218 | 1224 | 1260 | 1233 | 1289 | 1260 || avg 1013 ms
parallel stream:  455 |  378 |  376 |  380 |  377 |  372 |  376 |  371 |  374 |  376 |  369 |  372 |  382 |  379 |  375 |  370 |  369 |  376 |  516 |  376 || avg 385 ms

实验代码:

public static void main(String[] args) {
    int size = 30000;
    int count = 20;

    // random array
    int[][] arr = IntStream.range(0, size)
            .mapToObj(i -> IntStream.range(0, size)
                    .map(j -> (int) (1 + Math.random() * 10))
                    .toArray())
            .toArray(int[][]::new);

    benchmark("enhanced for", count, () -> maximumWealthEnhanced(arr));
    benchmark("for loop", count, () -> maximumWealthFor(arr));
    benchmark("parallel stream", count, () -> maximumWealthPStream(arr));
}
public static void benchmark(String name, int count, Runnable runnable) {
    int average = 0;
    System.out.print(String.format("%16s", name + ":"));
    for (int i = 0; i < count; i++) {
        long time = System.currentTimeMillis();
        runnable.run();
        time = System.currentTimeMillis() - time;
        System.out.print(" " + String.format("%4d", time) + " |");
        average += time;
    }
    average /= count;
    System.out.println("| avg " + average + " ms");
}
public static int maximumWealthEnhanced(int[][] accounts) {
    int max = 0;
    for (int[] account : accounts) {
        int sum = 0;
        for (int j = 0; j < account.length; j++) {
            sum += account[j];
        }
        max = Integer.max(max, sum);
    }
    return max;
}
public static int maximumWealthFor(int[][] accounts) {
    int max = 0;
    for (int i = 0; i < accounts.length; i++) {
        int sum = 0;
        for (int j = 0; j < accounts[i].length; j++) {
            sum += accounts[i][j];
        }
        max = Integer.max(max, sum);
    }
    return max;
}
public static int maximumWealthPStream(int[][] accounts) {
    return Arrays.stream(accounts).parallel()
            .mapToInt(arr -> Arrays.stream(arr).sum())
            .max().orElse(0);
}
柯翔
2023-03-14

在第一种方法中,您在内环和外环中使用传统的for循环,而在第二种方法中,您在外环中使用增强的for循环

 for (int[] account : accounts)

测试以测量运行时。

  1. 在accounts数组中创建了21个数组
  2. 循环使用两个不同的maximumWealth(int[][]acounts)
  • 首先我们使用增强的for循环
  • 在第二个我们使用传统的for循环

增强的for循环

public class Tryout {
    public static void main(String[] args) {
        int[][] accounts = {{3, 3, 5, 5, 4, 2, 2, 3, 1, 31, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2},
                {2, 3, 3, 3, 33, 3, 3, 3, 3, 3, 3, 3, 33, 32, 2, 21, 1, 1, 22, 3, 3, 3, 4, 4, 4, 4, 9, 8, 2, 3, 4},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {5, 0, 2, 92, 31},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5}};
        long startTime = System.nanoTime();
        int result = Tryout.maximumWealthEnhanced(accounts);
        long endTime = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println(totalTime);
    }

    public static int maximumWealthEnhanced(int[][] accounts) {
        int max = 0;
        for (int[] account : accounts) {
            int sum = 0;
            for (int j = 0; j < account.length; j++) {
                sum += account[j];
            }
            max = Integer.max(max, sum);
        }
        return max;
    }
}

运行时平均值

1. 37085 NS
2. 41154 NS
3. 47630 NS
4. 37348 NS
5. 39489 NS
6. 37107 NS
7. 37605 NS
8. 37096 NS
9. 37609 NS
10. 39255 NS

平均值=39137,0纳秒

传统for循环

public class Tryout {
    public static void main(String[] args) {
        int[][] accounts = {{3, 3, 5, 5, 4, 2, 2, 3, 1, 31, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2},
                {2, 3, 3, 3, 33, 3, 3, 3, 3, 3, 3, 3, 33, 32, 2, 21, 1, 1, 22, 3, 3, 3, 4, 4, 4, 4, 9, 8, 2, 3, 4},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {5, 0, 2, 92, 31},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5},
                {92, 92, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 2, 3, 4, 5}};
        long startTime = System.nanoTime();
        int result = Tryout.maximumWealth(accounts);
        long endTime = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println(totalTime);
    }

    public static int maximumWealth(int[][] accounts) {
        int max = 0;
        for (int i = 0; i < accounts.length; i++) {
            int sum = 0;
            for (int j = 0; j < accounts[i].length; j++) {
                sum += accounts[i][j];
            }
            max = Integer.max(max, sum);
        }
        return max;
    }
}

运行时平均值

1. 43645 NS
2. 42052 NS
3. 40661 NS
4. 40936 NS
5. 46346 NS
6. 46916 NS
7. 42064 NS
8. 39406 NS
9. 39572 NS
10. 40945 NS

平均值=42254,3纳秒

所以我不会说增强的速度快得多。我会说这是一个微小的纳秒,快一点。

这里需要注意的一件重要事情是,增强的for循环使用迭代器,因此,如果您使用迭代器手动迭代html" target="_blank">集合,那么您应该具有几乎相同的性能。

增强的for循环的好处是它很方便并且不容易出错,但是如果你想更好地控制迭代过程,那么使用传统的for循环。

资源:

  1. Java中for循环和增强的for循环之间的区别
  2. 为什么增强的for循环比普通的for循环更有效
 类似资料:
  • 问题内容: 我正在自学一些Java,并且坚持创建2D数组,该数组使用随机值对其进行初始化,然后创建该数组的转置。 示例输出为: 原始矩阵 转置矩阵 ^应该是最终输出。代码的一些帮助将不胜感激! 如果行或列的数量超出指定范围,我想编写代码以生成错误消息。以及是否从命令行读取矩阵元素而不是随机生成它们。 问题答案: 这是返回转置矩阵的int [] []的简单方法… 比起打印二维矩阵,您可以使用如下方法

  • 我已经创建了一个字符串数组,其中包含单词“磅”、“美元”和“欧元”,我想把这些标签放在旗帜的左边(为了用户应用程序的清晰性,因为不是每个用户都知道哪个货币属于哪个国家)。 我创建了一个循环,将创建一个标签,并将其分配到旗帜的左侧,它应该使一个"英镑"标签,然后一个"美元",然后一个"欧元"每次穿越Y轴南部,使他们与旗帜对齐然后,它将重置数组计数以返回到正确的字符串,沿着x轴移动并再次重复。然而,它

  • 我是java的新手,我正在编写这个简短的程序,您可以在其中猜测1到10之间的数字。正确的数字存储为整数。如果您猜测较低的数字,它应该说“正确的数字较高”,如果您猜测较高,它应该说“正确的数字较低”。这是我所拥有的: 所以很明显这是行不通的,因为如果你输入一个更小的数字,它会跳到下一个数字,即使这个数字更大,它也是正确的。那么,我如何解决这个问题,让它检查两个语句呢?抱歉解释得不好。谢了。

  • 问题内容: 我有一个像这样的3D矩阵 并希望将它们以网格格式堆叠,最后得到 有没有一种方法,而无需明确地对其进行hstacking(和/或vstacking)或添加额外的维度并重塑(不确定这样做是否可行)? 谢谢, 问题答案: In [27]: x = np.arange(16).reshape((4,2,2)) 我在这里发布了用于将数组重塑/取消塑形的更多常规功能。

  • 问题内容: 在知道数组索引的情况下,使用Arrays或HashMaps更好(在性能方面)吗?请记住,示例中的“对象数组/映射”只是一个示例,在我的真实项目中,它是由另一个类生成的,因此我不能使用单个变量。 ArrayExample: HashMapExample: HashMap看起来好得多,但我确实需要在此方面具有性能,因此具有优先权。 编辑: 那么是数组,仍然欢迎建议 编辑: 我忘了提,Arr

  • 问题内容: 当我的研究使我相信循环是PHP中最快的迭代构造…为了使它更清晰时,您认为以下哪个会更快? 示例一 示例二 我的逻辑是,在示例中的每次迭代中,在每次迭代中访问myLargeArray的长度比在示例二中访问简单的整数值要昂贵。那是对的吗? 问题答案: 第一种方法较慢,因为必须在循环的每次迭代中都调用该函数。该方法本身非常快,但是调用该函数仍然有一些开销。通过将其移动到循环之外,您正在执行所