Can we use a for-each loop to iterate objects of type Iterator?

If we do the following, we get an error:

class FGH{ public static Iterator reverse(List list) { Collections.reverse(list); return list.iterator(); } public static void main(String[] args) { List list = new ArrayList(); list.add("1"); list.add("2"); list.add("3"); /*for(Iterator it:reverse(list)) Iterator it=reverse(list);*/ for (Object obj: reverse(list)) System.out.print(obj + ", ");}} 

but if we modify such code, we will not get an error, does this mean that we cannot iterate over objects of type Iterator?

 class FGH{ public static Iterator reverse(List list) { Collections.reverse(list); return list.iterator(); } public static void main(String[] args) { List list = new ArrayList(); list.add("1"); list.add("2"); list.add("3"); Iterator it=reverse(list); while(it.hasNext()){ Object obj=it.next(); System.out.println(obj); } }} 
+1
java iterator
Jan 29
source share
6 answers

The for loop in your first example assumes reverse(list) is a collection of Iterator , which of course is not. That is why this example will not work.

In general, you can only use foreach for classes that implement Iterable . Iterator not one of these classes.

See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Iterable.html

+5
Jan 29 '10 at 15:29
source share

Many answers suggest that iterators are not iterable. This is true, but such an answer does not affect why.

The reason for each loop is to repeat the iteration so that the same object goes through several times (so you can use several cycles for each cycle on the same object without unexpected behavior), while the iterator allows only one traversal, If for each permitted use of iterators, the behavior will be unexpected for programmers who did not understand that their iterators would be exhausted after the start of the loop.

If you use an API that gives you iterators, and you want to use iterations, you have two ways to solve this problem:

  • Create an anonymous iterative class, the iterator() method calls an API function that returns an iterator. Thus, each time you use the for-each loop for an iterable, this API function is called again, returning a new (and inexhaustible) iterator.
  • Make a one-pass iterative wrapper class that takes an iterator and allows one call to iterator() . On subsequent calls, select AssertionError or IllegalStateException , if necessary.
+4
Jan 29
source share

You would use the extended for loop as follows:

 for (Object o : list) 
0
Jan 29
source share

As stated above, you need to reference Iterable (or array) in each block. For example, when you do the following:

 Collection<String> coll = ...; for (String str : coll) { ... } 

In fact, the following happens:

 Collection<String> coll = ...; for (Iterator<String> iter = coll.iterator(); iter.hasNext(); ) { String str = iter.next(); } 

To do this, the argument must implement Iterable (for example, have a public iterator() method that returns Iterator (or be an array). Thus, your code should look like this:

 class FGH { public static void main(String[] args) { List list = new ArrayList(); list.add("1"); list.add("2"); list.add("3"); while (Object obj : Collections.reverse(list)){ System.out.println(obj); } } } 
0
Jan 29 '10 at 16:14
source share

The syntax for each is for collections ( Iterable , to be precise), and not for iterators. I am trying to figure out the arguments why Java was created this way in this question .

The simplest solution for you would be to return a reverse list (which is iterable) instead of a list iterator. Then you can use the shorthand loop syntax.

In the question mentioned earlier , the hacker path is described using the Adapter class, which wraps Iterator as Iterable and returns Iterator on the first call to iterator() . Look at the adapter code, it is quite simple. It serves the purpose, but since an iterator can only be used once, it is somewhat invalid Iterable (it will not be able to create a second iterator).

A key difference in behavior appears when you use it twice:

 for(Object a : foo) { } for(Object a : foo) { } 

will process all elements in foo twice if it is Iterable correct, but only once if it uses the adapter I painted - the second loop will do nothing.

0
Jun 26 '12 at 23:20
source share

First you need to wrap Iterator in Iterable . Here is the Java 8 solution:

 for (Object obj : (Iterable<Object>) () -> reverse(list)) System.out.print(obj + ", "); 

Or just use Iterator.forEachRemaining() :

 reverse(list).forEachRemaining(obj -> System.out.print(obj + ", ")); 
0
Dec 21 '16 at 6:40
source share



All Articles