将Iterator向前移动到for语句和while语句之间的区别

时间:2009-02-05 11:49:24

标签: java iterator for-loop while-loop

当我使用对象的迭代器时,我使用 while循环(如每本书中学习Java所写的那样,如 Thinking in Java 的Bruce Eckel):

Iterator it=...

while(it.hasNext()){
    //...
}

但有时我看到的是有人使用 for循环

Iterator it=...
for (Iterator it=...; it.hasNext();){
    //...
}

我不明白这个选择:

  • 当我有一个带有序数序列(作为数组)的集合或带有一个特殊的步骤规则(通常声明为简单的增量counter++)时,我使用 for循环
  • 当循环结束时我使用 while循环我没有这个约束但只有退出的逻辑条件。

这是一个没有其他原因的样式编码问题,或者存在一些我不知道的其他逻辑(例如性能)?

感谢您的每一个反馈

5 个答案:

答案 0 :(得分:32)

for循环的正确语法是:

for (Iterator it = ...; it.hasNext(); ){
    //...
}

(代码中的前一个声明是多余的,以及for循环标题中的额外分号。)

无论您使用此语法还是while循环是一个品味问题,两者都转换为完全相同。 for循环的通用语法是:

for (<init stmt>; <loop cond>; <iterate stmt>) { <body>; }

相当于:

<init stmt>;
while (<loop cond>) { <body>; <iterate stmt>; }

编辑:实际上,上述两种形式并不完全等效, if (如问题中所述)变量是用init语句声明的。在这种情况下,迭代器变量的范围会有所不同。对于for循环,范围仅限于循环本身,在while循环的情况下,范围扩展到封闭块的末尾(没有什么大惊喜,因为声明在循环之外)。

此外,正如其他人所指出的,在较新版本的Java中,for循环有一个简写符号:

for (Iterator<Foo> it = myIterable.iterator(); it.hasNext(); ) {
    Foo foo = it.next();
    //...
}

可以写成:

for (Foo foo : myIterable) {
    //...
}

使用此表单,您当然会丢失对迭代器的直接引用,这是必要的,例如,如果要在迭代时从集合中删除项目。

答案 1 :(得分:9)

这只是一种风格的东西,就像你在使用带索引的东西时我更喜欢for循环。如果你正在使用Java 5,你当然应该在集合上使用foreach循环:

Collection<String> someCollection = someCollectionOfString();
for (String element : someCollection) {
....
}

答案 2 :(得分:9)

在for循环中声明Iterator的目的是最小化变量的范围,这是一个很好的做法。

当您在循环外部声明Iterator时,循环完成后引用仍然有效/有效。 99.99%的时间,一旦循环完成,你不需要继续使用Iterator,所以这样的风格可能会导致这样的错误:

//iterate over first collection
Iterator it1 = collection1.iterator();
while(it1.hasNext()) {
   //blah blah
}

//iterate over second collection
Iterator it2 = collection2.iterator();
while(it1.hasNext()) {
   //oops copy and paste error! it1 has no more elements at this point
}

答案 3 :(得分:4)

这两种方法之间没有太大区别,除了第一种方法在循环之后记住it的值。第二种方法可能会引发错误,因为您在循环内重新声明了变量。

实际上还有第三种方法。而不是写作。

for (Iterator<SomeObject> it = foo.iterator(); it.hasNext();) {
  SomeObject so = foo.next();
}

你最常写的是

for (SomeObject so: foo) {...}

这两个相同的东西......

答案 4 :(得分:2)

人们可以使用显式('旧样式')循环,因为它对他们来说感觉更干净,也许他们还没有调整到新的语法(我个人认为它更清洁)。

循环结构的更长时间的一个实际特定优点是你有一个对迭代器的引用,因此可以调用除next()之外的方法。特别是,hasNext()通常可用于调用 - 想象一下,如果要打印出以逗号分隔的字符串列表:

StringBuilder sb = new StringBuilder();
for (Iterator it=...; it.hasNext();){
   sb.append(it.next());
   if (it.hasNext())
      sb.append(", ");
}

如果您使用更详细的for循环,那么只能区分“这是最后一个”这样的情况。