Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

for each and non-java.util.* collections

0 views
Skip to first unread message

Aryeh M. Friedman

unread,
Apr 23, 2006, 2:13:43 PM4/23/06
to
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

unread,
Apr 23, 2006, 1:47:26 PM4/23/06
to
Aryeh M. Friedman wrote:
> 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
--
Unemployed English Java programmer
http://jroller.com/page/tackline/

Aki Tuomi

unread,
Apr 23, 2006, 2:49:33 PM4/23/06
to
Aryeh M. Friedman kirjoitti:

for(Integer i: c) {
..
}

Hendrik Maryns

unread,
Apr 24, 2006, 6:07:49 AM4/24/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Thomas Hawtin schreef:


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

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

Chris Uppal

unread,
Apr 24, 2006, 7:22:19 AM4/24/06
to
Hendrik Maryns wrote:

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

unread,
Apr 24, 2006, 7:53:19 AM4/24/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chris Uppal schreef:


> Hendrik Maryns wrote:
>
>>> 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.

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

Message has been deleted

Chris Uppal

unread,
Apr 24, 2006, 11:31:07 AM4/24/06
to
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>.

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

unread,
Apr 25, 2006, 4:38:01 AM4/25/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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

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

Hendrik Maryns

unread,
Apr 25, 2006, 4:47:47 AM4/25/06
to
-----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-----

Chris Uppal

unread,
Apr 25, 2006, 5:01:15 AM4/25/06
to
Stefan Ram wrote:

[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


Chris Uppal

unread,
Apr 26, 2006, 5:30:55 AM4/26/06
to
Hendrik Maryns wrote:

> 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


0 new messages