【问题标题】:I want to use the normal for loop instead of the special one我想使用普通的 for 循环而不是特殊的循环
【发布时间】:2020-04-22 16:50:24
【问题描述】:

Contact 是一个带有参数化构造函数的公共类,其中getPhoneNumber() 作为方法之一,下面的代码位于不同的类中,其中:

List<Contact> list=new ArrayList<Contact>();

这是我现在使用的代码:

for(Contact contact:list)
{
  n=contact.getPhoneNumber();
  if(num==n)
    return contact
}

如何按以下格式编写此代码:

for(i=0;i<list.size();i++)
{
...
...
...
}

【问题讨论】:

  • 你看过the docs吗?
  • "这是我现在使用的代码:" 有什么问题吗?为什么要放弃它?
  • 欢迎来到 Stack Overflow。请注意,正如the help section 所说,您应该在考虑在这里提问之前进行搜索和研究。我写这篇文章是因为我发现你的问题似乎没有得到很好的研究。
  • "if(num==n)" 这意味着您将电话号码表示为数字(这是不好的,例如因为您不能表示以 0 开头的数字);或者您是通过身份而不是平等来比较引用(这可能不是您真正想要的)。
  • 请注意,如果在某些时候您的列表将是 LinkedList,那么每个 get(index) 都需要从头开始,因此要获取第 N 个元素,它需要从 1 开始迭代, 2,3,..N 到达您的元素,使其非常低效。您当前的 for-each 循环通过在内部使用 Iterator 解决了这个问题,它记住列表中的当前元素,因此它可以简单地跳转到下一个。

标签: java class object arraylist java-8


【解决方案1】:

这是您要求的答案。这是否是您应该想要的答案,我不确定。

    for (int i = 0; i < list.size(); i++)
    {
        Contact contact = list.get(i);
        String n = contact.getPhoneNumber();
        if (Objects.equals(n, num))
        {
            return contact;
        }
    }

我假设getPhoneNumber() 返回Stringnull。最好在循环内声明n,但你当然必须将它声明为getPhoneNumber() 返回的类型。如果它返回原始类型(例如intlong,但不推荐),请使用== 进行比较,就像您的问题一样。

Andreas 和 Pshemo 都警告不要像我在这段代码中那样使用 list.get(i),以防列表被 LinkedList 或其他没有恒定时间元素查找的列表替换。首先,无论如何都不应该使用LinkedList。其次,如果有理由使用list.get(i)(不过我不知道这些原因应该是什么),请通过在循环之前放置以下断言语句来防止性能下降(并确保您在开发中启用了断言计算机和您的测试环境中):

    assert list instanceof RandomAccess : "Check whether " + list.getClass() + " performs well enough";

或者您可以使用流。这当然不是您要求的,但如果仅针对其他读者,我想补充的是,许多程序员更喜欢流操作:

    return list.stream()
            .filter(c -> Objects.equals(c.getPhoneNumber(), num))
            .findFirst()
            .orElse(null);

【讨论】:

    【解决方案2】:

    您已经在使用的增强型for 循环没有任何问题,这就是我编写代码的方式。但是你说过要改用传统的for,所以...

    您基本上按照自己的方式进行操作,并在循环体中使用 get 或(在一般情况下更好)使用循环迭代器(有关使用迭代器的更多信息,请参阅 Andreas' answer)。

    但是:

    1. 你需要声明i

    2. 我倾向于不喜欢重复调用size,而是将其保存到变量中。不过,这可能是过早的微优化。

    例如:

    for (int i = 0; i < list.size(); i++) {
        Contact contact = list.get(i);
        n = contact.getPhoneNumber(); // I assume `n` is already declared?
        if (num == n) {
            return contact;
        }
    }
    

    for (int i = 0, len = list.size(); i < len; i++) {
        Contact contact = list.get(i);
        n = contact.getPhoneNumber(); // I assume `n` is already declared?
        if (num == n) {
            return contact;
        }
    }
    

    但同样,请参阅 Andreas' answer 以了解使用迭代器的示例,在一般情况下这是更好的选择。

    【讨论】:

      【解决方案3】:

      如果您想将增强for 循环转换为常规for 循环,那么您应该查看Java Language Specification,它记录了编译器是如何做到这一点的。

      你的循环:

      for (Contact contact : list) {
          n = contact.getPhoneNumber();
          if (num == n)
              return contact
      }
      

      编译器将其转换为以下内容(因为listIterable,而不是数组)

      for (Iterator<Contact> iter = list.iterator(); iter.hasNext(); ) {
          Contact contact = iter.next();
          n = contact.getPhoneNumber();
          if (num == n)
              return contact
      }
      

      您执行此操作与编译器执行此操作的唯一区别是您现在可以访问上面代码中名为 iterIterator 变量。


      警告:不要使用索引循环和list.get(i),除非您绝对确定列表是ArrayList (或非常小),并且您知道该列表将来永远不会更改为其他内容。由于这种保证非常罕见,所以不要这样做。

      LinkedList 等列表中按索引查找非常慢。使用Iterator 将在所有列表类型中表现良好。

      【讨论】:

      • 我不知道我今天早上在想什么。当然使用迭代器。
      • 使用迭代器没有区别,增强的 for 循环只是迭代器的语法糖,不是吗?
      • @Jean-BaptisteYunès 正如答案中已经提到的,编译器为增强的for 循环生成了一个迭代器循环,所以你是对的。
      • @andreas 我的评论更多是针对 T.J.,使用迭代器不会改变任何东西......
      • @Jean-BaptisteYunès 那么您应该使用@T.J.Crowder 来确保将通知 TJ 您的评论,并向其他人澄清您正在与 TJ 交谈,而不是评论答案。再说了,TJ已经承认他知道了,所以你的评论真的是多余的。
      【解决方案4】:

      在每次迭代中,您只需要使用get(int) 方法获取联系人即可。从那里开始,列表的主体应该是相同的:

      for (i=0; i < list.size(); i++) {
        Contact contact = list.get(i);
        n = contact.getPhoneNumber();
        if (num == n) {
          return contact;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-27
        • 2011-10-06
        • 2017-04-03
        • 2020-08-14
        • 1970-01-01
        相关资源
        最近更新 更多