Java Forum / General / April 2006
for each and non-java.util.* collections
Aryeh M. Friedman - 23 Apr 2006 19:13 GMT If I have the following class:
import java.util.Iterator;
// the simplest possible collection that does something useful with all the Iterator mandated // methods public class MyCollection<T> implements Iterable, Iterator { private T[] arr; private int pos;
public MyCollection() { arr=(T[]) arr; pos=0; }
public Iterator<T> iterator() { return this; }
public boolean hasNext() { return pos!=arr.length; }
public T next() { return arr[pos++]; }
public void remove() { T[] tmp=(T[]) new Object[arr.length-1]; int i=0;
for(i=0;i<pos-1;i++) tmp[i]=arr[i];
for(i=pos;i<arr.length;i++) tmp[i]=arr[i];
arr=tmp; } }
and I write a test class for it:
public class MyCollectionTest { public static void main(String[] args) { MyCollection<Integer> c=new MyCollection<Integer>();
for(Object i:c) System.out.println(i); } }
stuff works fine (except for the obvious need to case i if I was going to use it as a T)... now if I do for(Integer i:c) I get:
Incompatible types: java.lang.Object but expected java.lang.Integer
Am I missing something about generics, iterators and/or foreach?
Thomas Hawtin - 23 Apr 2006 18:47 GMT > public class MyCollection<T> implements Iterable, Iterator public class MyCollection<T> implements Iterable<T>, Iterator<T>
But I strongly suggest it does not implement Iterator itself.
Tom Hawtin
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Hendrik Maryns - 24 Apr 2006 11:07 GMT Thomas Hawtin schreef:
>> public class MyCollection<T> implements Iterable, Iterator > > public class MyCollection<T> implements Iterable<T>, Iterator<T> > > But I strongly suggest it does not implement Iterator itself. Why? I’ve done this before too, and don’t see a problem in it.
I.e. public Iterator iterator { return this; }
H. - -- Hendrik Maryns
================== http://aouw.org Ask smart questions, get good answers: http://www.catb.org/~esr/faqs/smart-questions.html
Chris Uppal - 24 Apr 2006 12:22 GMT > > But I strongly suggest it does not implement Iterator itself. > > Why? I've done this before too, and don't see a problem in it. > > I.e. public Iterator iterator { return this; } How do you handle two simulataneous iterations ? Or are your objects (when viewed as Iterators) stateless ? I can't see how that can work.
Anyway, an iterator and the collection it iterates over, are two completely different things. I don't see any advantage, and /considerable/ scope for confusion, in conflating the two.
-- chris
Hendrik Maryns - 24 Apr 2006 12:53 GMT Chris Uppal schreef:
>>> But I strongly suggest it does not implement Iterator itself. >> Why? I've done this before too, and don't see a problem in it. [quoted text clipped - 3 lines] > How do you handle two simulataneous iterations ? Or are your objects (when > viewed as Iterators) stateless ? I can't see how that can work. Good point. I’ll have to have a look at it, and probably change it indeed. The reason was, that I have some classes computing combinatorics, and their main use is to iterate over all possible combinations/variations/permutations/... of the array that is given to them. So actually, they are iterators. Now it is very convenient to make them implement Iterable, in order to be able to do this:
Integer[] integerArray; // initialise array for (Integer[] indices : new Combinator<Integer>(integerArray, 5) ){ // indices goes through all combinations of 5 out of the integer // array }
Unfortunately, this is not possible if Combinator only implements Iterator. And I think it’s a bit convoluted to create an extra wrapper class implementing Iterable and returning a Combinator. But indeed simultaneous iterations is asking for problems. I suppose I’ll just put that in the doc, though.
> Anyway, an iterator and the collection it iterates over, are two completely > different things. I don't see any advantage, and /considerable/ scope for > confusion, in conflating the two. I agree with you point, that you should not mix a collection and its iterator. However, you seem to forget that iterators not necessarily are bound to some collection. As my example above, an iterator can iterate through other things, too. (Ok, in the end, that is a collection too, but one that does never actually exist: there is no point in actually creating all elements of the collection, as they are fully predictable.)
H. - -- Hendrik Maryns
================== http://aouw.org Ask smart questions, get good answers: http://www.catb.org/~esr/faqs/smart-questions.html
Chris Uppal - 24 Apr 2006 16:31 GMT > Good point. I'll have to have a look at it, and probably change it > indeed. The reason was, that I have some classes computing [quoted text clipped - 12 lines] > Unfortunately, this is not possible if Combinator only implements > Iterator. I think you are thinking of it the wrong way around. The Combinator is (or would be if you did this /my/ way ;-) a factory for iterators. The iterators themselves have no independent existence (there's no real need for a public class, for instance). So your code snippet remains unchanged, but most of the iteration logic moves out of Combinator<T>, and into an inner class which implements Iterable<T>.
BTW, if you do that you can, if you choose, make your Iterator iterate over permutations of a List (or array) which is held in the Combinator (rather than only over /indexes/ into that List). I don't know whether you would prefer that way of doing things, but that's the way I've chosen to do it in my own code.
> However, you seem to forget that iterators not necessarily > are bound to some collection. As my example above, an iterator can > iterate through other things, too. I agree, I was using the language rather loosely. Or rather, ambiguously -- the word collection certainly includes "virtual collections" (such as the set of all permutations of <something>), but it can also be taken to refer to Java's Collections which are all concrete containers (rather than general collections) and -- as such -- misnamed.
-- chris
Hendrik Maryns - 25 Apr 2006 09:38 GMT Chris Uppal schreef:
>> Good point. I'll have to have a look at it, and probably change it >> indeed. The reason was, that I have some classes computing [quoted text clipped - 19 lines] > iteration logic moves out of Combinator<T>, and into an inner class which > implements Iterable<T>. I commit this sounds better than what I have now. That will be the umpteenth TODO in the Task list...
> BTW, if you do that you can, if you choose, make your Iterator iterate over > permutations of a List (or array) which is held in the Combinator (rather than > only over /indexes/ into that List). I don't know whether you would prefer > that way of doing things, but that's the way I've chosen to do it in my own > code. It does already. The example was not well-chosen, but you could replace Integer with any class in the above example. You can see the code on http://mindprod.com/jgloss/combination.html.
H. - -- Hendrik Maryns
================== http://aouw.org Ask smart questions, get good answers: http://www.catb.org/~esr/faqs/smart-questions.html
Hendrik Maryns - 25 Apr 2006 09:47 GMT Hendrik Maryns schreef:
> Chris Uppal schreef: >>> Hendrik Maryns wrote: [quoted text clipped - 24 lines] > I commit this sounds better than what I have now. That will be the > umpteenth TODO in the Task list... OTOH, the classes aren’t meant to persist anyway, so just as easy to create a new Combinator(someArrayIalreadyHave) as first assigning a combinator to a variable and asking for its iterator method (or indeed using it in foreach).
They are only utility classes, so I don’t know whether it is very useful to create yet another iterator class just for the benefit of being this little more robust. Hm, I don’t like what I am writing here, maybe it is. I mean, doing one iteration would involve creating two classes then, neither of which will probably be reused.
H. - -- Hendrik Maryns
================== http://aouw.org Ask smart questions, get good answers: http://www.catb.org/~esr/faqs/smart-questions.html
Chris Uppal - 26 Apr 2006 10:30 GMT > Hm, I don't like what I am writing here, [...] ;-)
Come now, Hendrik, you know you aren't going to be happy until you've changed the implementation...
-- chris
Stefan Ram - 24 Apr 2006 14:38 GMT >How do you handle two simulataneous iterations ? Do you mean nested iterations? (Another interpretation could be iterations in two threads.)
A type implementing both »Iterator« and »Iterable« as if by
public java.util.Iterator iterator(){ return this; }
is called an »iteration« by me.
An example for nested iterations:
public class Main { public static void main( final java.lang.String[] args ) { for( java.lang.Integer i : new de.dclj.ram.system.iteration.IntegralRange( 10, 12 )) java.lang.System.out.println( i );
for( de.dclj.ram.type.tuple.Tuple i : new de.dclj.ram.system.iteration.TupleNesting <java.lang.Integer,java.lang.Integer> ( new de.dclj.ram.system.iteration.IntegralRange( 1, 3 ), new de.dclj.ram.system.iteration.IntegralRange( 2, 5 ))) java.lang.System.out.println( i ); }}
This prints:
10 11 12 ( 1; 2 ) ( 1; 3 ) ( 1; 4 ) ( 1; 5 ) ( 2; 2 ) ( 2; 3 ) ( 2; 4 ) ( 2; 5 ) ( 3; 2 ) ( 3; 3 ) ( 3; 4 ) ( 3; 5 )
The first loop is an example of a simple iteration.
The second shows an iteration combinator combining two iterations into a new nested iteration. (I believe, you asked whether this is possible.)
I also could have used two nested for-loops. The above code only was written with the intention to also demonstrate »TupleNesting«
~~~
The source code for the types used should be browsable as part of my ram.jar publication:
http://www.purl.org/stefan_ram/pub/ram-jar
(The »distribution« on this page is an older version, possibly not containing the types used here. But the link »Online API-specification with links to online-source code« should lead to the source code. This is a preliminary and incomplete pre-alpha publication of my library only. I am in the process of preparing an alpha release.)
~~~
Another example: How to get the comma separated segments from the file »tmp.txt«?
1,2,3 alpha, beta, 3
Answer: Combine a line iteration with a segment iteration:
public class Main { public static void main( final java.lang.String[] args ) { de.dclj.ram.java.io.LineReadableAndClosable reader = new de.dclj.ram.java.io.DefaultLineReadableAndClosable ( new java.io.BufferedReader ( new de.dclj.ram.java.io.FileReader ( new de.dclj.ram.java.io.DefaultPath( "tmp.txt" )).getFileReader() )); for( java.lang.String i : new de.dclj.ram.system.iteration.DependentNesting <java.lang.String,java.lang.String> ( new de.dclj.ram.java.io.Lines( reader ), de.dclj.ram.java.lang.StringSegments.class )) java.lang.System.out.println( i ); }}
This prints:
1 2 3 alpha beta 3
(StringSegments objects always use the comma "," as a separator, customizing them to use another seperator might be possible in a later version.)
Chris Uppal - 25 Apr 2006 10:01 GMT [me:]
> > How do you handle two simulataneous iterations ? > > Do you mean nested iterations? No (though I like the idea and may even "borrow" it ;-). All I was talking about was the case where you have two iterators active on the same collection (in the wide sense) at the same time.
E.g if you have a method which does a pairwise scan over two collections:
boolean check(Iterable<Something> a, Iterable<Something> b) { Iterator<Something> overA = a.iterator(); Iterator<Something> overB = b.iterator();
while (overA.hasNext() && overB.hasNext()) if (someRelationshipBetween(a.next(), b.next()) return true;
return false; }
There is no reason why it should not be called with a == b, but Hendrik's current implementation (unecessarily, as it turns out) does not allow that.
-- chris
Aki Tuomi - 23 Apr 2006 19:49 GMT Aryeh M. Friedman kirjoitti:
> If I have the following class: > [quoted text clipped - 63 lines] > > Am I missing something about generics, iterators and/or foreach? for(Integer i: c) { .. }
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|