The Source for Java Technology Collaboration

Home » java.net Forums » JDK » Java SE

Thread: Make java.util.Iterator usable in a for statement

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 11 - Last Post: Mar 22, 2005 12:15 PM by: vpatryshev
subanark

Posts: 143
Make java.util.Iterator usable in a for statement
Posted: Jan 4, 2005 4:12 PM
  Click to reply to this thread Reply

Under the current symantics only classes which implement java.lang.Iterable may be used in a "foreach" statement. Since all this interface requires is to return an Iterator, it would be nice if there was a special case for Iterator.
I find that I end up with an iterator and not an Iterable often since I use legacy code that does not implement this interface, or I'm using a class which can be iterated in multiple ways.
for(Object o:myObj.getIterator())
{ ... }


The only reason I can think that having an iterator would not be allowed in a for statement is that Iterator is not in java.lang or one of its subpackages.


Message was edited by: subanark


tackline

Posts: 238
Re: Make java.util.Iterator usable in a for statement
Posted: Jan 5, 2005 3:07 AM   in response to: subanark
  Click to reply to this thread Reply

Some EA versions of the compiler permitted iterators in the enhanced for, IIRC.

I guess the problem is that the iterator is available to other statements, causing non-obvious behaviour. I'm quite happy that the facility has disappeared. In any case, it is better for APIs to return Collection types, as they are more flexible. There are not many cases where you do not want to hold onto all the objects at once, or ca not find the length (at all) if requested.

You can always load the elements of an Iterator (or Enumeration) into a Collection first. Off hand and without a compiler to check:

public static <T> Collection<T> collect(Iterator<T> iter) {
` ` Collection<T> collection = new ArrayList<T>();
` ` while (iter.hasNext()) {
` ` ` ` collection.add(iter.next());
` ` }
` ` return collection;
}

` ` for (String name : collect(request.getParameterNames())) {
` ` ` ` ...
` ` }

nick1304

Posts: 1
Re: Make java.util.Iterator usable in a for statement
Posted: Jan 5, 2005 1:49 PM   in response to: subanark
  Click to reply to this thread Reply

A simple "hack" would be to create a IteratorLooper implments Iterable. It could accept an Iterator in its constructor and then just return that iterator in the iterator() call...

vpatryshev

Posts: 37
Re: Make java.util.Iterator usable in a for statement
Posted: Mar 22, 2005 12:09 PM   in response to: nick1304
  Click to reply to this thread Reply

Thanks for the good idea. I hope you do not object if I use it in my Iterators class on myjavatools.com

pauldv

Posts: 2
Re: Make java.util.Iterator usable in a for statement
Posted: Feb 3, 2005 1:53 AM   in response to: subanark
  Click to reply to this thread Reply

> The only reason I can think that having an iterator
> would not be allowed in a for statement is that
> Iterator is not in java.lang or one of its
> subpackages.

The problem is more subtle. The contract of an Iterable is that one can create an iterator over the Iterable repeatedly. It is not possible to reiterate an iterator.

In short, doing this would create unintuitive behaviour from the for loop. Such as the element to be iterated over, being invalid after use.

vpatryshev

Posts: 37
Re: Make java.util.Iterator usable in a for statement
Posted: Mar 22, 2005 12:11 PM   in response to: pauldv
  Click to reply to this thread Reply

Well, I would not agree. If possible, yes, it is good to be able to reproduce the iterator; but Iterable is still good even if it can return the iterator just once. E.g. bytes(Reader reader) - you cannot require the reader to be resettable, so what, that's life.

jwenting

Posts: 478
Re: Make java.util.Iterator usable in a for statement
Posted: Feb 4, 2005 12:44 AM   in response to: subanark
  Click to reply to this thread Reply

An Iterator is a specific construct that handles its own iteration.
What you're trying to do is iterate externally over something that iterates internally, this leads to undefined behaviour.

Learn to use the correct means to iterate instead of trying to change the language to work around your misconceptions.

markf

Posts: 34
Re: Make java.util.Iterator usable in a for statement
Posted: Feb 4, 2005 9:29 AM   in response to: subanark
  Click to reply to this thread Reply

The problem isn't with the enhanced for loop or with iterators -- the problem is the legacy code. Better to spend effort improving and refactoring that legacy code than introduce troublesome, nonintuitive behaviour for iterators and enhanced for loops.

vpatryshev

Posts: 37
Re: Make java.util.Iterator usable in a for statement
Posted: Feb 7, 2005 12:12 PM   in response to: subanark
  Click to reply to this thread Reply

It is not a big deal to implement, I think. The background iterable ought to look like this:

Iterable<T> iterateOnce(final Iterator<T> iterator) {
  public Iterator<T> iterator() { return iterator; }
}
 


And, say, introduce a coersion that makes an Iterator an Iterable in the right context.

As to the thin difference between an Iterable and Iterator that "Iterable" can return an Iterator many times, this is not necessary true. It is easy to imagine a singleton Iterator returned by and Iterable - so to say, "Iterable only once". You open an input stream, you do not iterate through it over and over again, right? But if it is a file, you can iterate through it as many times as you like.

cbare

Posts: 21
Re: Make java.util.Iterator usable in a for statement
Posted: Mar 21, 2005 10:41 PM   in response to: subanark
  Click to reply to this thread Reply

OK, I'll buy the explaination that something like this:

List<Widgets> list = getWidgets();

is probably better practice than:

Iterator<Widgets> iterator = getWidgetsIterator();

Also, code like this would be broken:

// match up all combinations of drinks and food
for (Drink drink : DrinkCollection) {
for (Food food : FoodIterator) {
System.out.println("You could have "
+ food + " and " + drink + "!");
}
}

The inner loop dies on the second pass of the outer loop. But, I still expected an Iterator to be iterable. All this protecting me from myself makes me want to go code up some non-bounds-checked array accesses in C just to keep my edge.

seanreilly

Posts: 13
Re: Make java.util.Iterator usable in a for statement
Posted: Mar 22, 2005 7:42 AM   in response to: cbare
  Click to reply to this thread Reply

Use this:

public class IteratorContainer<T> implements Iterable<T>
{
private final Iterator<T> it;
public IteratorContainer(final Iterator<T> i)
{
this.it = i;
}

public java.util.Iterator<T> iterator()
{
return this.it;
}
}

Then use it like this:
Iterator<Widget> iterator = getWidgetIterator();
for (Widget w: new IteratorContainer<Widget>(iterator))
{
//do something with the widget
}

vpatryshev

Posts: 37
Re: Make java.util.Iterator usable in a for statement
Posted: Mar 22, 2005 12:15 PM   in response to: cbare
  Click to reply to this thread Reply

I do not think it would be a good idea to mix the notions of Iterator and Iterable. An Iterable is something that can return an iterator, and maybe not once; an Iterator, on the other hand, never goes back. On some occasions, like in the case of list, you can be kind of agnostic here, but lists are not all we have in life.




 XML java.net RSS