使用 for 语句和 while 语句向前移动迭代器之间的区别

Difference between moving an Iterator forward with a for statement and a while statement

提问人: 提问时间:2/5/2009 最后编辑:6 revs, 5 users 49%alepuzio 更新时间:9/22/2017 访问量:36755

问:

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

Iterator it=...

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

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

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

我不明白这个选择:

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

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

感谢您的每一次反馈

Java 迭代器 for-loop while 循环

评论

0赞 Vadzim 7/29/2015
stackoverflow.com/questions/2598219/ 中有一个转换为与 for-each 循环兼容的示例......IteratorIterable

答:

9赞 2 revs, 2 users 92%MrWiggles #1

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

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

评论

1赞 Bill Michell 2/5/2009
使用这种形式的迭代器的唯一损失是无法调用 Iterator.remove() 方法 - 因为您没有对 Iterator 对象的引用。
1赞 tddmonkey 2/5/2009
真。。但你会很快发现这一点!
32赞 2 revsDavid Hanak #2

for 循环的正确语法是:

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

(代码中的前面声明是多余的,for 循环标题中的额外分号也是多余的。

无论你使用这种语法还是循环是一个品味问题,两者都是完全一样的。for 循环的一般语法是:while

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

这相当于:

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

编辑:实际上,如果(如问题中)变量是用 init 语句声明的,则上述两种形式并不完全等价。在这种情况下,迭代器变量的作用域将有所不同。使用 for 循环时,作用域仅限于循环本身,但是,在 while 循环的情况下,作用域扩展到封闭块的末尾(这并不奇怪,因为声明在循环之外)。

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

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

可以写成:

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

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

评论

0赞 Michael Rutherfurd 2/6/2009
如果您添加对使用“for”循环获得的有限范围的引用,这将成为完美的答案......
2赞 Andrzej Doyle #3

人们可能仅仅因为他们感觉更干净而使用显式(“旧样式”)循环,也许他们还没有适应新语法(我个人认为新语法要干净得多)。

较长的 for 循环构造的一个实际特定优点是,您具有对迭代器的引用,因此可以在迭代器上调用除 .特别是,调用通常很有用 - 想象一下,如果你想打印出一个逗号分隔的字符串列表:next()hasNext()

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

如果您使用更冗长的 for 循环,则仅用于区分“这是最后一个”的情况。

4赞 Henrik Paul #4

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

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

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

你最常可以写

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

这两者等于同一回事......

9赞 matt b #5

在 for 循环中声明 的目的是最小化变量的作用域,这是一种很好的做法。Iterator

当您声明循环的外部时,引用在循环完成后仍然有效/有效。99.99% 的情况下,一旦循环完成,你就不需要继续使用 ,所以这样的样式会导致这样的错误:IteratorIterator

//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
}