Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the extended for loop not work for iterators? [duplicate]

Tags:

java

for-loop

Possible Duplicate:
Why is Java's Iterator not an Iterable?

We all know java's extended for loop:

List<X> list = ...
for(X x : list) { ... }

What I need is:

Iterator<X> listIterator = ...
for(X x : listIterator){ ... }

Java does not allow this. I was wondering if there's a good reason why the specification does not support this.

Here's my usecase:

I'm writing a reader for a kind of file format. Such a file contains entries that are to be read. For the sake of the example assume that I'm trying to reinvent BufferedReader and my elements are Strings.

I'm quite unhappy with the API style of the original BufferedReader which forces me to write ugly code like:

for(String line = reader.readLine(); line != null; line = reader.readLine(){
   ...
}

I'd rather have something nice like

for(String line : reader){
   ...
}

Of course I can make my BufferedReader implement Iterable<String>. But this implies that there is a iterator() method that might be called several times. Since I cannot seek in the file, I cannot really support multiple parallel iterators.

Having my BufferedReader implement Iterator<String> instead of Iterable<String> seems far more reasonable. But then I can't use the for statement :-(

like image 295
Stefan Avatar asked Apr 10 '26 19:04

Stefan


1 Answers

Because the contract for the foreach loop is to iterate over every element. If it was allowed to just take an Iterator you could give it a half-consumed Iterator and it wouldn't know the difference.

Set<String> set = new HashSet(Arrays.asList(new String [] {"One", "Two", "Three"}));
Iterator i = set.iterator();
// Consume the first.
String first = i.next();
for ( String s : i ) { // Error here.

}

I accept that it would make things easier but it could also introduce some serious bugs because you wont know you have covered all entries in the collection.

// Works fine because Set is Iterable and the contract is satisfied 
// that this will iterate over <b>all</b> of the entries.
for ( String s : set ) {
}

You can always hack it around by making a transient Iterable. I cant test this right now but something like:

for ( String s : new Iterable { 
  public iterator<String> () {
    return set.iterator ();
  }
} ) {
}

Cumbersome but it should work.

like image 89
OldCurmudgeon Avatar answered Apr 12 '26 09:04

OldCurmudgeon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!