【问题标题】:Incorrect logic in my loop我的循环中的逻辑不正确
【发布时间】:2015-08-14 18:21:20
【问题描述】:
public static void main(String[] args) {
        Integer[] courses1 = {1,2,3};
        Integer[] courses2 = {0,1};

        Integer[] longestArr;
        Integer[] shortestArr;
        ArrayList commonCourses = new ArrayList();

        if ( courses1.length > courses2.length)
        {
            longestArr = courses1; shortestArr = courses2;
        }    
        else
        {    
            longestArr = courses2; shortestArr = courses1;
        }

        for ( int i : longestArr)
        {
            for ( int j : shortestArr)
            {
                if (i == j);
                   commonCourses.add(i); 
            }
        } 
        Collections.sort(commonCourses);
        System.out.println(commonCourses.size());


}

无论 course1 和 course2 的值是什么,当它应该只包含两个数组中的元素时,arrayList commonCourses 的大小总是比两个数组中的元素总数大一倍。

我有 2 个问题,为什么将 2 个数组中的元素添加到 arrayList,为什么 arrayList 的大小总是比元素总数大一?

如果您想知道为什么我一开始就声明了课程 1 和课程 2,这是我在 Eclipse 上测试的来自 TalentBuddy.co 的问题。我用不同的起始条件进行了测试,总是发生同样的事情。

我的新瘦身解决方案

public static void main(String[] args) {
        Integer[] courses1 = {1};
        Integer[] courses2 = {0};

        ArrayList <Integer>commonCourses = new ArrayList<Integer>();

        for ( int i : courses1)
        {
            for ( int j : courses2)
            {
                if (i == j)
                   commonCourses.add(i); 
            }
        } 
        Collections.sort(commonCourses);
        System.out.println(commonCourses.size());     
}

【问题讨论】:

  • 另外,为什么需要“最短”和“最长”?
  • 你可以用一个循环来做到这一点。不需要嵌套循环
  • 我认为如果我在外部循环中使用最短的数组,它会有一个数组越界异常,但使用增强的 for 循环我发现不会发生

标签: java arrays loops arraylist


【解决方案1】:

你的问题是这一行的分号:

if (i == j);

if 子句到此结束,始终执行以下行。

【讨论】:

    【解决方案2】:

    if 条件末尾的分号是您的问题。有关为什么会发生这种情况的详细说明,请参阅this StackOverflow post. 简而言之,分号导致编译器在运行时忽略条件。

    for ( int j : shortestArr)
    {
        if (i == j);
        //         ^  Remove this semi-colon
        commonCourses.add(i); 
    }
    

    使用花括号来格式化 if 语句有助于防止这种情况发生:

    if(condition){
        doSomething();
    }
    

    【讨论】:

    • 你链接的那篇文章中的建议提供了很好的建议,总是使用大括号,这可能永远不会发生。
    • 我不同意添加大括号会防止这种情况发生。他的编码风格是下一行开始大括号,添加大括号但留下无关的分号不会改变任何事情。现在,使用一个好的 IDE(例如 Eclipse)很可能会警告您您的代码可疑,这样可以防止出现类似的错误。
    • @Andreas 我用 Eclipse 调试了他的代码,并没有抛出任何警告。可能在一些智能定制之后,它会提前识别问题,但默认情况下不会。
    • @Trobbins 我刚刚将原始代码粘贴到 Eclipse 中,并在编辑器中收到了多个警告。代码编译并运行没有错误,但编辑器显示黄色警告。忽略有关泛型的警告会留下我所指的警告,该警告标记在有问题的分号上:“空控制流语句”。
    • 检查您的设置:Windows > Preferences > Java > Compiler > Error/Warnings,部分“潜在的编程问题”>“Empty statement”,并确保将其设置为“Warning”。更好的是,如果您有一点时间,将所有“忽略”更改为“警告”(留下“错误”),然后只忽略您不关心的少数警告(例如“非外部化字符串”)。跨度>
    【解决方案3】:
     for ( int j : shortestArr)
     {
          if (i == j);
                  // ^ REMOVE THIS SEMICOLON
               commonCourses.add(i); 
     }
    

    问题是多余的分号。您的代码块现在在功能上与此相同:

     for ( int j : shortestArr)
     {
          if (i == j)
          {
          }
    
          commonCourses.add(i); 
     }
    

    【讨论】:

      【解决方案4】:

      if 条件后面有一个误用的分号。

      if (i == j);
      

      【讨论】:

      • No, i is definitely not the index。否则,像String s : stringArray 这样的东西根本不起作用。并且自动拆箱将Integer 转换为int,这使它们成为==-comparable。
      【解决方案5】:

      我从未在一家公司工作过,如果:

      if (...) {
         ...
      }
      

      而且原因很明显。

      让我展示最抽象的解决方案:

      • 课程是一组唯一的课程编号
      • 普通课程是一个交叉集
      • 在 java 中,使用抽象接口(如 Set)作为变量,但可以使用不同的实现类来实现该集合
      • 想要一个有序集合,TreeSet就是这样一个实现

        Set<Integer> courses1 = new HashSet<>();
        Collections.addAll(courses1, 1, 2, 3);
        
        SortedSet<Integer> courses2 = new HashSet<>();
        Collections.addAll(courses2, 0, 1);
        
        SortedSet<Integer> commonCourses = new TreeSet<>(courses1);
        commonCourses.retainAll(courses2);
        

      【讨论】:

      • 我还没有遇到过套装(或在公司工作过!),但我会研究它们,它看起来像是一个优雅的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 2014-02-27
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 2018-01-10
      相关资源
      最近更新 更多