for each and non-java.util.* collections

T

Thomas Hawtin

Aryeh said:
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
 
A

Aryeh M. Friedman

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=arr;

for(i=pos;i<arr.length;i++)
tmp=arr;

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?
 
A

Aki Tuomi

Aryeh M. Friedman kirjoitti:
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=arr;

for(i=pos;i<arr.length;i++)
tmp=arr;

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?


for(Integer i: c) {
..
}
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Thomas Hawtin schreef:
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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFETKN1e+7xMGD3itQRAghHAJ9feb0DiNvI4ZBDNtmIzRRIxCHmNwCfUG6N
FgBlf0A66ae3TT2h4hK9DyU=
=3Sfj
-----END PGP SIGNATURE-----
 
C

Chris Uppal

Hendrik said:
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
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chris Uppal schreef:
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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFETLwve+7xMGD3itQRAmo6AJwM6/mSSXXWtq/Lg2MgDCOSmQSrEgCfXdOd
An+fistEJ/h5im1G5be/4mc=
=L3yM
-----END PGP SIGNATURE-----
 
S

Stefan Ram

Chris Uppal said:
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.)
 
C

Chris Uppal

Hendrik said:
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.

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
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chris Uppal schreef:
Hendrik said:
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.

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>.

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFETd/pe+7xMGD3itQRAuzgAJ43V7JNnW6zqgZu9RpqM9j8dlpjlQCfSeBa
Id7PerHzixogHmWgQ33B7Mw=
=6Nmt
-----END PGP SIGNATURE-----
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hendrik Maryns schreef:
Chris Uppal schreef:
Hendrik Maryns wrote:

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.
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>.

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFETeIze+7xMGD3itQRAuKhAJ9bK2tKMZE6964fdiZsG2XGUrEBUQCeMnMR
obXPFrUZWXKFWVBm9kxeF0Y=
=I8a+
-----END PGP SIGNATURE-----
 
C

Chris Uppal

Stefan Ram wrote:

[me:]
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
 
C

Chris Uppal

Hendrik said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top