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

Posted

技术标签:

【中文标题】使用 for 语句和 while 语句向前移动迭代器的区别【英文标题】:Difference between moving an Iterator forward with a for statement and a while statement 【发布时间】:2010-10-05 15:49:34 【问题描述】:

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

Iterator it=...

while(it.hasNext())
    //...

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

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

我不明白这个选择:

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

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

感谢您的每一个反馈

【问题讨论】:

在***.com/questions/2598219/…中有一个将Iterator转换为兼容for-each循环Iterable的例子 【参考方案1】:

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) 
    //...

使用这种形式,您当然会失去对迭代器的直接引用,这是必需的,例如,如果您想在迭代时从集合中删除项目。

【讨论】:

如果您添加对使用“for”循环获得的有限范围的引用,这将成为完美的答案......【参考方案2】:

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

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

【讨论】:

使用这种形式的迭代器唯一会失去的是你不能调用 Iterator.remove() 方法——因为你没有对 Iterator 对象的引用。 没错.. 但你很快就会发现这一点!【参考方案3】:

在 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

【讨论】:

【参考方案4】:

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

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

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

你最常写

for (SomeObject so: foo) ...

这两个等于同一个东西……

【讨论】:

【参考方案5】:

人们可能会使用显式('旧样式')for循环,只是因为他们觉得它更干净,也许他们还没有适应新语法(我个人认为它更干净)。

较长的 for 循环构造的一个实际特定优势是您可以引用迭代器,因此可以在其上调用除 next() 之外的方法。特别是,hasNext() 调用起来通常很有用 - 想象一下,如果您想打印一个以逗号分隔的字符串列表:

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

如果你使用更冗长的for循环,这只是为了区分“这是最后一个”的情况。

【讨论】:

以上是关于使用 for 语句和 while 语句向前移动迭代器的区别的主要内容,如果未能解决你的问题,请参考以下文章

循环语句while与for的穷举迭代

python基础之循环与迭代器

迭代器当中的死循环导致内存溢出

ECMAScript5语句

for语句

Linux C 编程学习第四天_循环语句_while_do/while_for_goto