java—在2d数组中循环性能问题

js81xvg6  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(297)

**结束。**此问题需要详细的调试信息。它目前不接受答案。
**想改进这个问题吗?**更新问题,使其成为堆栈溢出的主题。

六天前关门了。
改进这个问题
为什么下面的未注解代码要比注解掉的代码快得多?leetcode初学者在这里,我真的看不出两者之间的区别。

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;
    }
}
kknvjkwl

kknvjkwl1#

进行实验

取一个二维数组 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);
}
z5btuh9x

z5btuh9x2#

差异

你的第一种方法 maximumWealth(int[][] acounts 在内部循环和外部循环中使用传统的for循环,而在外部循环中使用的第二种方法中使用增强的for循环

for (int[] account : accounts)

实验

测试运行时间。
在accounts数组中创建了21个数组
用两个不同的maximumwealth(int[][]acounts)循环遍历它
首先,我们使用增强的for循环
在第二个循环中,我们使用传统的for循环
停止以纳秒为单位的执行时间。
执行步骤3十次,然后计算平均值
以纳秒为单位比较平均值

哪个环路更快?

增强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循环使用迭代器,因此如果您使用迭代器手动迭代集合,那么您应该具有几乎相同的性能。
增强的for循环的好处是它方便而且不容易出错,但若您想要对迭代过程有更多的控制,那个么就使用传统的for循环。
资源:
java中for循环和增强for循环的区别
为什么增强的for循环比普通的for循环更有效

相关问题