break语句会使我的代码更快吗?

时间:2017-04-07 10:25:13

标签: java loops for-loop runtime break

我本来应该编写一个代码来说明一个数组是否有重复。运行时并不重要。我认为我的下面的代码会有O(n²),因为我使用了嵌套的for循环。我知道有比我写的更好更快的代码,但我的问题是我在if语句中创建的break语句是否会使我的代码更快一些?它应该让它更快,因为程序知道"嘿,我们发现重复,我们可以停止搜索更多"。我曾经从一位同学那里听说,如果我避免使用returnbreak等语句,代码会更好/更稳定。太糟糕了我当时没有足够的关心来问为什么。也许你可以告诉我这是否属实?

如果他是对的,这些陈述会伤害"我的代码,还有更好的解决方法吗?

public class FindDuplicate{
    public static void main(String[] args){
        int[] A={1,2,3,4,5,6,7,8,4};
        boolean bool=false;
        for(int i=0; i<A.length; i++){
            for(int j=0; j<A.length; j++){
                if(A[i]==A[j] && i!=j){
                    bool=true;
                    break;
                }
            }
        }
        if(bool==true){
            System.out.print("Duplicate found");
        }else{
            System.out.print("No duplicate found");
        }
    }
}

2 个答案:

答案 0 :(得分:2)

  

我的问题是我在if语句中创建的break语句   会让我的代码(有点)更快吗?

但是,并非在所有情况下,在大多数情况下,考虑到当您找到自己之后的内容时不必继续迭代,它确实会使您的代码更快。

下面的算法包含两个嵌套循环。外部循环遍历所有数组的N项,因此需要O(N)个步骤。 对于通过外部循环的每次旅行,内部循环也迭代数组中的N项,因此它也是takes O(N)步。 由于一个循环嵌套在另一个循环中,因此组合性能为O(N × N) = O(N2)

for(int i = 0; i < A.length; i++){
    for(int j=0; j < A.length; j++){
       if(A[i] == A[j] && i != j){
           bool = true;
           break;
       }
    }
}

我们可以通过在外循环的每次迭代中不返回j = 0来使您的算法更快一些。

for(int i = 0; i < A.length; i++){
  for(int j = i+1; j < A.length; j++){
     if(A[i] == A[j]){
         bool = true;
         break;
     }
  }
}

请注意,在这种情况下,我们不需要检查&& i != j,因为它们永远不会相等。

  

我曾经从一位同学那里听说代码更好/更多   如果我避免返回或中断等语句

,则稳定

使用JVM时,break规范未说明是否存在性能损失。简而言之,没有任何证据表明使用breakreturn会使您的代码不稳定(不管怎样我都不知道)。我会说的唯一情况&#34;哦,这不是一个好的做法&#34;是你过度使用单词break的时候。但是,在许多情况下break是唯一可能更快完成任务的可能性,例如您当前的解决方案。基本上,为什么当你找到你所追求的东西后继续进行迭代?我认为return也不是&#34;一个不好的做法&#34;因为类似于break,为什么在你不需要时继续执行代码,这肯定会让你的代码更快。

我们能否更快地找到重复算法?

当然我们可以考虑java中的Set接口,该接口不允许重复,并且它基于散列表数据结构,因此插入平均需要O(1)次。通过使用HashSet,一个通用Set实现,我们可以在O(n)时间内找到重复项。由于HashSet仅允许使用唯一元素,因此当您尝试添加重复项时,add()方法将失败并返回false

<强>解决方案:

public static boolean hasDuplicate(int[] array) {
      Set<Integer> dupes = new HashSet<Integer>();
      for (Integer i : array) {
          if (!dupes.add(i)) {
             return true; // we have found a duplicate
          }
      }
      return false; // no duplicate
}

答案 1 :(得分:1)

实际上,您不需要bool标志变量,也不需要使用breakreturn将停止迭代,如果没有找到重复,则返回false:

private static boolean findDuplicateOriginal(int[] A) {
    for(int i=0; i<A.length; i++){
        for(int j=0; j<A.length; j++){
            if(A[i]==A[j] && i!=j){
                return true;
            }
        }
    }
    return false;
}

只需指出性能不应该是编码时的唯一目标。您应该担心维护或编写较少/干净的代码,因为担心性能。 它取决于上下文(调用该函数的频率,它应该执行多少次迭代,它将使用paralelStream运行吗?...)您的应用程序运行以选择一种或另一种方式。

有很多帖子谈论循环性能与流性能以及支持和反对意见:

我只想向您展示干净(1行!)是否对同一个purpouse使用Java8语法:

import java.util.Arrays;

public class test {

public static void main(String[] args) {
    int[] A = {1,2,3,4,5,6,7,8,9};
    System.out.println(Arrays.toString(A) + " using findDuplicate >> " + findDuplicate(A));
    System.out.println(Arrays.toString(A) + " using findDuplicateOriginal >>" + findDuplicateOriginal(A));

    int[] B = {1,1,3,4,5,6,7,8,4};
    System.out.println(Arrays.toString(B) + " using findDuplicate >> " + findDuplicate(B));
    System.out.println(Arrays.toString(B) + " using findDuplicateOriginal >> " + findDuplicateOriginal(B));
}

// using streams
private static boolean findDuplicate(int[] items) {
    return !(Arrays.stream(items).distinct().count() == items.length);
}

// refactored original version
private static boolean findDuplicateOriginal(int[] A) {
    for(int i=0; i<A.length; i++){
        for(int j=0; j<A.length; j++){
            if(A[i]==A[j] && i!=j){
                return true;
            }
        }
    }
    return false;
}
}

输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9] using findDuplicate >> false
[1, 2, 3, 4, 5, 6, 7, 8, 9] using findDuplicateOriginal >>false
[1, 1, 3, 4, 5, 6, 7, 8, 4] using findDuplicate >> true
[1, 1, 3, 4, 5, 6, 7, 8, 4] using findDuplicateOriginal >> true