Java中的迭代器与Foreach

背景: 迭代器 是集合框架提供的一个接口,用于遍历集合并对集合中的项进行顺序访问。

null
      // Iterating over collection 'c' using iterator   for (Iterator i = c.iterator(); i.hasNext(); )        System.out.println(i.next());

每人 循环用于遍历集合中的项。

   // Iterating over collection 'c' using for-each    for (Element e: c)       System.out.println(e);

我们将每个循环中使用的“:”读作“in”。所以循环读作“对于元素中的每个元素e”,这里的元素是存储元素类型项的集合。

注: 在使用lambda表达式的Java8中,我们可以简单地用

elements.forEach (e -> System.out.println(e) );

两次遍历之间的差异 在for each循环中,我们不能修改集合,它将抛出一个 ConcurrentModificationException 另一方面,通过迭代器,我们可以修改集合。

修改集合只意味着删除集合中存储的元素或更改其内容。这是因为for each循环隐式地创建了一个迭代器,但它不向用户公开,因此我们无法修改集合中的项。

何时使用哪种遍历?

  • 如果我们必须修改集合,我们可以使用迭代器。
  • 在使用嵌套for循环时,最好使用每个循环,考虑下面的代码以更好地理解。

JAVA

// Java program to demonstrate working of nested iterators
// may not work as expected and throw exception.
import java.util.*;
public class Main
{
public static void main(String args[])
{
// Create a link list which stores integer elements
List<Integer> l = new LinkedList<Integer>();
// Now add elements to the Link List
l.add( 2 );
l.add( 3 );
l.add( 4 );
// Make another Link List which stores integer elements
List<Integer> s= new LinkedList<Integer>();
s.add( 7 );
s.add( 8 );
s.add( 9 );
// Iterator to iterate over a Link List
for (Iterator<Integer> itr1=l.iterator(); itr1.hasNext(); )
{
for (Iterator<Integer> itr2=s.iterator(); itr2.hasNext(); )
{
if (itr1.next() < itr2.next())
{
System.out.println(itr1.next());
}
}
}
}
}


输出:

Exception in thread "main" java.util.NoSuchElementException    at java.util.LinkedList$ListItr.next(LinkedList.java:888)    at Main.main(Main.java:29)

上面的代码抛出了java。util。没有什么例外。

在上面的代码中,我们一次又一次地调用itr1的next()方法(即List l)。现在,我们正在推进迭代器,甚至没有检查它在集合(在内部循环中)中是否还有更多元素,因此,我们推进迭代器的速度超过了集合中的元素数量,这导致了NoTouchElementException。

每个循环都是为嵌套循环量身定制的。用下面的代码替换迭代器代码。

JAVA

// Java program to demonstrate working of nested for-each
import java.util.*;
public class Main
{
public static void main(String args[])
{
// Create a link list which stores integer elements
List<Integer> l= new LinkedList<Integer>();
// Now add elements to the Link List
l.add( 2 );
l.add( 3 );
l.add( 4 );
// Make another Link List which stores integer elements
List<Integer> s= new LinkedList<Integer>();
s.add( 2 );
s.add( 4 );
s.add( 5 );
s.add( 6 );
// Iterator to iterate over a Link List
for ( int a:l)
{
for ( int b:s)
{
if (a<b)
System.out.print(a + " " );
}
}
}
}


输出:

2 2 2 3 3 3 4 4

性能分析

使用for-each循环或迭代器遍历集合可以获得相同的性能。这里,性能指的是这两种遍历的时间复杂度。

如果您使用老式的C for循环进行迭代,那么我们可能会大幅增加时间复杂度。 //这里l是列表,它可以是ArrayList/LinkedList,n是列表的大小

for (i=0;i<n;i++)   System.out.println(l.get(i));

这里,如果列表l是ArrayList,那么我们可以在O(1)时间内访问它,因为它被分配了连续的内存块(就像一个数组),也就是说,随机访问是可能的。但是,如果集合是LinkedList,那么随机访问是不可能的,因为它没有分配连续的内存块,所以为了访问一个元素,我们必须遍历链接列表,直到到达所需的索引,因此在最坏的情况下访问一个元素所用的时间将是O(n)。

对于没有随机访问的集合,迭代器和for each循环比简单for循环快,而在允许随机访问的集合中,for each循环/for循环/迭代器的性能没有变化。

相关文章: Java中的迭代器 在Java中从集合中检索元素(针对每个元素、迭代器、ListIterator和EnumerationIterator) 参考资料: https://docs.oracle.com/javase/8/docs/technotes/guides/language/foreach.html https://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html https://stackoverflow.com/questions/2113216/which-is-more-efficient-a-for-each-loop-or-an-iterator

本文由 希拉格·阿加瓦尔 .如果你喜欢GeekSforgek,并且想贡献自己的力量,你也可以写一篇文章,并将文章邮寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享