【问题标题】:Efficient loop code? Also, a query about the "for each" loop高效的循环代码?另外,关于“for each”循环的查询
【发布时间】:2013-12-25 12:35:27
【问题描述】:

以下代码编译并执行我需要的操作。它遍历一个基于 int 的多维数组(称为 nums),并搜索所有出现的值 1。该程序的输出如下所示。需要注意三点:

  • 关于“外部 for”循环语句,我使用 Java 的逗号运算符声明了两个附加变量。
  • 另外关于这个“外部 for”,我在“迭代部分”中使用了另一个逗号运算符来重置这些附加变量之一。
  • 关于“inner for”,我在“迭代部分”中使用了另一个逗号运算符来增加这个附加变量。
int[][] nums = {{1,1,2},{3,4},{5},{6,7,8},{9,1,1}};

for (int i=0, elsSearched=0, foundCount=0; i < nums.length; i++, elsSearched=0) {
    for (int j=0; j < nums[i].length; j++, elsSearched++) {
        if (nums[i][j] == 1) {
            foundCount++;
        }
    }
    System.out.println("Searched " + elsSearched + 
" elements, and found \'number one\' a total of " + foundCount + " times..");
}       

程序输出:

这段代码能写得更高效/更优雅吗?

我的另一个问题是关于 Java 的“for each”循环。我尝试使用带有逗号运算符的“for each”循环重写上面的代码,但代码无法编译。我很快得出了明显的结论,但是如果可以使用逗号运算符,“for each”循环会更好,还是只会引入“分散注意力的混乱”?

【问题讨论】:

  • 我不认为你可以更有效地做到这一点,因为你必须至少查看每个元素一次以判断它是否是一个;)
  • 另请参阅this answer,了解 for-each 循环与 for 循环的效率。

标签: java for-loop


【解决方案1】:

如果您遇到性能问题,您可以尝试在子数组上使用二分搜索(如果您的数组始终是排序的)。

int valueToSearch = 1;

for(int[] inner : nums){

     int foundIndex = Arrays.binarySearch(inner, valueToSearch);

      if (foundIndex >= 0){
          foundCount ++;
       }

}

所以你会得到 O(n * log(n) ) 而不是 O(n^2) 的性能。

我猜你必须做一些基准测试。但最重要的是要知道你的输入是什么样子的。比你能找到最好的算法。

【讨论】:

    【解决方案2】:

    首先,您可能不应该优化某些东西,直到您证明它对您的程序运行时有重要贡献。话虽如此,为什么不试试这个呢……

    int foundCount = 0;
    int totalCount = 0;
    for (final int[] i : nums) { // foreach int[] in nums
      for (final int v : i) {    // foreach value v in the int[] from nums
        switch (v) {             // switch on a constant int...
        case 1:                  // The value we seek.
          ++foundCount;          // Add to the foundCount, and fall through!
        default:
          ++totalCount;
        }
      }
    }
    System.out.println("Searched a total of " + totalCount + 
                " elements and found '#1' a total of " + foundCount);
    

    【讨论】:

    • 我很好奇,为什么是final 关键字?有性能优势还是只是一个安全网?
    • 是的。当事物是不可变的(运行时和编译器可以优化)以及使用switchif 时,可以进行优化。
    • 不确定只有 3 个目标的跳跃表,但我同意决赛。可惜优雅和效率并不总是一样的。
    【解决方案3】:

    编辑:请注意,foundCount到目前为止发现的元素总数,因为它永远不会重置为零。这是故意的吗?

    你不同意这段代码更容易阅读和更简洁吗? (注意:效率和你的代码一样)

    int[][] nums = {{1,1,2},{3,4},{5},{6,7,8},{9,1,1}};
    
    int foundCount = 0; 
    for(int[] inner : nums){
        for(int i : inner){
            if (i == 1){
                foundCount++;
            }
        }
        System.out.println("Searched " + inner.length + 
                    " elements, and found \'number one\' a total of " + foundCount + " times..");
    }
    

    输出:

    Searched 3 elements, and found 'number one' a total of 2 times..
    Searched 2 elements, and found 'number one' a total of 2 times..
    Searched 1 elements, and found 'number one' a total of 2 times..
    Searched 3 elements, and found 'number one' a total of 2 times..
    Searched 3 elements, and found 'number one' a total of 4 times..
    

    【讨论】:

    • 太好了,谢谢。是的,'foundCount' 功能符合预期,是的,我同意你的观点,你的代码更容易阅读,更简洁。谢谢。
    猜你喜欢
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2015-11-10
    • 1970-01-01
    • 2013-08-07
    • 2012-09-20
    • 1970-01-01
    • 2019-05-04
    相关资源
    最近更新 更多