iterator over superclass of collection

F

Frank Fredstone

I want to expose an iterator over a collection, where the iterator
returns elements that are a super class of the actual
objects. Essentially, so I can implement interfaces.

Or, another way to do what I think looks like the intention of this
illegal code:

given: Collection<PrivateAye> c;
Iterator<Aye> it = c.iterator();

PrivateAye below is the internal implementation of the Aye interface
that also extends another class.

Is there a simpler way than what I have in the iterator method below:

public interface Aye {
String aye();
}

public class A {
private String a;
public A(String eh) { a = eh; }
String a() { return a; }
}

import java.util.Iterator;
import java.util.Vector;

public class X implements Iterable<Aye> {
private class PrivateAye extends A implements Aye {
private int code = 0;
public PrivateAye(String eh, int n) {
super(eh);
setCode(n);
}
public int getCode() { return code; }
public void setCode(int n) { code = n; }
public String aye() { return a(); }
}

private Vector<PrivateAye> ayes;

public static void main(String[] args) throws Exception {
X x = new X();
x.go();
}

public void go() throws Exception {
ayes = new Vector<PrivateAye>();
ayes.add(new PrivateAye("a", 0));
ayes.add(new PrivateAye("b", 1));
for (Aye a : this) {
System.out.println(a.aye());
}
}

public Iterator<Aye> iterator() {
return new Iterator<Aye>() {
private Vector<? extends Aye> vec = ayes;
private Iterator<? extends Aye> it = vec.iterator();
public boolean hasNext() { return it.hasNext(); }
public Aye next() { return it.next(); }
public void remove() { it.remove(); }
};
}
}
 
T

Tom Hawtin

Frank said:
I want to expose an iterator over a collection, where the iterator
returns elements that are a super class of the actual
objects. Essentially, so I can implement interfaces.

public Iterator<Aye> iterator() {
return new Iterator<Aye>() {
private Vector<? extends Aye> vec = ayes;
private Iterator<? extends Aye> it = vec.iterator();
public boolean hasNext() { return it.hasNext(); }
public Aye next() { return it.next(); }
public void remove() { it.remove(); }
};
}

This code needn't be so specific:

public static <T> Iterator<T> iterator(
Iterable<? extends T> iterable
) {
final Iterable<? extends T> target = iterable.iterator();
return new Iterator<T>() {
public boolean hasNext() {
return target.hasNext();
}
public T next() {
return target.next();
}
public void remove() {
target.remove();
}
};
}

Tom Hawtin
 
D

Daniel Pitts

I want to expose an iterator over a collection, where the iterator
returns elements that are a super class of the actual
objects. Essentially, so I can implement interfaces.

Or, another way to do what I think looks like the intention of this
illegal code:

given: Collection<PrivateAye> c;
Iterator<Aye> it = c.iterator();

PrivateAye below is the internal implementation of the Aye interface
that also extends another class.

Is there a simpler way than what I have in the iterator method below:

public interface Aye {
String aye();

}

public class A {
private String a;
public A(String eh) { a = eh; }
String a() { return a; }

}

import java.util.Iterator;
import java.util.Vector;

public class X implements Iterable<Aye> {
private class PrivateAye extends A implements Aye {
private int code = 0;
public PrivateAye(String eh, int n) {
super(eh);
setCode(n);
}
public int getCode() { return code; }
public void setCode(int n) { code = n; }
public String aye() { return a(); }
}

private Vector<PrivateAye> ayes;

public static void main(String[] args) throws Exception {
X x = new X();
x.go();
}

public void go() throws Exception {
ayes = new Vector<PrivateAye>();
ayes.add(new PrivateAye("a", 0));
ayes.add(new PrivateAye("b", 1));
for (Aye a : this) {
System.out.println(a.aye());
}
}

public Iterator<Aye> iterator() {
return new Iterator<Aye>() {
private Vector<? extends Aye> vec = ayes;
private Iterator<? extends Aye> it = vec.iterator();
public boolean hasNext() { return it.hasNext(); }
public Aye next() { return it.next(); }
public void remove() { it.remove(); }
};
}

}

Your concept is wrong.

Consider if you COULD do what you ask.

Collection<PrivateAye> ayes = new ArrayList<PrivateAye>();
Iterator<Aye> iterator = ayes.iterator();
iterator.next();
iterator.set(new SomeOtherAye());

Whoops, your PrivateAye array contains something that isn't a private
aye!!!!

Now, what you might be trying to solve:

public void seeAyes(Iteratble<Aye> ayes) {
// do something with the ayes
}
seeAyes(new ArrayList<PrivateAye>()); // compile error.
--- Instead, try this:
public <T extends Aye> void seeAyes(Iteratble<T> ayes) {
// do something with the ayes
}

seeAyes(new ArrayList<PrivateAye>()); // works fine!
 
F

Frank Fredstone

Tom Hawtin said:
I guess you could just use Iterator<? extends Aye> and Iterable<?
extends Aye>.

Can I implement Iterable<? extends Aye>? My compiler says class or
interface without bounds required.

In your more generic vresion doesn't the final make the code not thread safe?

End of message
 
T

Tom Hawtin

Frank said:
Can I implement Iterable<? extends Aye>? My compiler says class or
interface without bounds required.

I mean just use the iterator straight from the vector:

public Iterator<? extends Aye> iterator() {
return ayes.iterator();
}
In your more generic vresion doesn't the final make the code not thread safe?

Iterators are not thread-safe. You need to use locking over the entire
loop. See for instance Collections.synchronizedList. So to be
thread-safe the iteration in your go method would need a synchronized block.

final can in fact be used to make code thread-safe, but I'm not going to
go through "final field semantics" here. Suffice to say, making
variables, particular fields, final is a very good idea.

Tom Hawtin
 
F

Frank Fredstone

Tom Hawtin said:
I mean just use the iterator straight from the vector:

public Iterator<? extends Aye> iterator() {
return ayes.iterator();
}

But then that wouldn't match Iterable said:
Iterators are not thread-safe. You need to use locking over the entire
loop. See for instance Collections.synchronizedList. So to be
thread-safe the iteration in your go method would need a synchronized
block.
final can in fact be used to make code thread-safe, but I'm not going
to go through "final field semantics" here. Suffice to say, making
variables, particular fields, final is a very good idea.

Err.. I confused final with static, and thought there were static
local variables, for a moment.

I was hoping that I had missed some typical way, using wildcards, to get
Iterator<Aye> in my super-class of Iterable<Aye> from my backing
collection of PrivateAye objects, instead of having to write a special
case Iterator class to instantiate in the iterator method.
 
L

Lew

Frank said:
But then that wouldn't match Iterable<Aye>.

No, but it would give you what you need from an iterator.

Does this give you enough of what you want?

<scce>
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class WildIteration
{
static interface Aye
{
void doIt();
}

static class PrivateAye implements Aye
{
public void doIt()
{
System.out.println( "PrivateAye.doIt()" );
}
}

public static void main( String [] args )
{
List<PrivateAye> pis = new ArrayList<PrivateAye>();
pis.add( new PrivateAye() );

Collection <? extends Aye> c = pis;
Iterator<? extends Aye> it = c.iterator();
while ( it.hasNext() )
{
Aye aye = it.next();
aye.doIt();
}
}
}
</scce>
 
C

Chris Smith

Frank Fredstone said:
But then that wouldn't match Iterable<Aye>.

The important point here is that you REALLY want a value of the more
general type Iterable<? extends Aye>, and not an Iterable<Aye>. That
more general type correctly expresses the idea you want: namely, an
Iterable that returns elements which are assignment-compatible with Aye.
If you have an Iterable<Aye>, you can assign it to the wildcard type;
but if you have an Iterable<PrivateAye>, as you do here, you can still
assign it to the wildcard type.

By contrast, the type Iterable<Aye> is incorrect; it doesn't express
what you want. It's close enough that it passes for correct in some
cases; but you've found a case where it doesn't. The best solution is
not to write a type adapter of some kind, but to fix the type to express
what you really wanted anyway.

In general, wildcard types are also more restrictive in terms of
allowable operations. For Iterable and Iterator, though, there is no
additional restriction at all. It is never necessary to use an
Iterable<T> as opposed to the more general wildcard type
Iterable<? extends T>.
 
F

Frank Fredstone

Chris Smith said:
The important point here is that you REALLY want a value of the more
general type Iterable<? extends Aye>, and not an Iterable<Aye>. That
more general type correctly expresses the idea you want: namely, an
Iterable that returns elements which are assignment-compatible with Aye.

But that isn't what I want. Here is the scenario again. I have a class
that is a collection of instances of an interface, it is an iterable
collection of Ayes.

In the collection class I want to have a private implementation of
that interface. Below, my class can't extend a wildcard capture, and I
really don't want it to, because people aren't supposed to be able to
create instances of the interface, nor are they supposed to set
anything in the collection.

Below is the code I have. My question is still if there is something,
probably involving wildcards that would make it so that I don't have
to create an anonymous iterator class in my iterator method below. My
motivation is to clear up what looks like it could be a gap in my
understanding of generics.

import java.util.Iterator;
import java.util.Vector;

public class X implements Iterable<Aye> {
private class PrivateAye extends A implements Aye {
private int code = 0;
public PrivateAye(String eh, int n) {
super(eh);
setCode(n);
}
public int getCode() { return code; }
public void setCode(int n) { code = n; }
public String aye() { return a(); }
}

private Vector<PrivateAye> ayes;

public static void main(String[] args) throws Exception {
X x = new X();
x.go();
}

public void go() throws Exception {
ayes = new Vector<PrivateAye>();
ayes.add(new PrivateAye("a", 0));
ayes.add(new PrivateAye("b", 1));
for (Aye a : this) {
System.out.println(a.aye());
}
}

public Iterator<Aye> iterator() {
return new Iterator<Aye>() {
private Vector<? extends Aye> vec = ayes;
private Iterator<? extends Aye> it = vec.iterator();
public boolean hasNext() { return it.hasNext(); }
public Aye next() { return it.next(); }
public void remove() { it.remove(); }
};
}
}
 
H

Hendrik Maryns

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

Frank Fredstone schreef:
But that isn't what I want. Here is the scenario again. I have a class
that is a collection of instances of an interface, it is an iterable
collection of Ayes.

In the collection class I want to have a private implementation of
that interface. Below, my class can't extend a wildcard capture, and I
really don't want it to, because people aren't supposed to be able to
create instances of the interface, nor are they supposed to set
anything in the collection.

It’s not because it extends a wildcard capture that people will suddenly
be able to create instances of the interface or set anything. You allow
them to if you provide them the methods.
Below is the code I have. My question is still if there is something,
probably involving wildcards that would make it so that I don't have
to create an anonymous iterator class in my iterator method below. My
motivation is to clear up what looks like it could be a gap in my
understanding of generics.

I suggest you read the Java generics document about wildcards once more.
They really aren’t evil.
import java.util.Iterator;
import java.util.Vector;

Consider using ArrayList, see the thread Efficiency -- Vectors above.
public class X implements Iterable<Aye> {
private class PrivateAye extends A implements Aye {
private int code = 0;
public PrivateAye(String eh, int n) {
super(eh);
setCode(n);
}
public int getCode() { return code; }
public void setCode(int n) { code = n; }
public String aye() { return a(); }
}

private Vector<PrivateAye> ayes;

private ArrayList<Aye> would suffice here, from what you do with it below.

Otherwise, what is your problem with using ArrayList<? extends Aye>
here? It is private anyway, so nobody can do anything with it.

You’ll have to explain what you need the PrivateAye class for, to make
the point clearer.
public static void main(String[] args) throws Exception {
X x = new X();
x.go();
}

public void go() throws Exception {
ayes = new Vector<PrivateAye>();
ayes.add(new PrivateAye("a", 0));
ayes.add(new PrivateAye("b", 1));
for (Aye a : this) {
System.out.println(a.aye());
}
}

public Iterator<Aye> iterator() {
return new Iterator<Aye>() {
private Vector<? extends Aye> vec = ayes;
private Iterator<? extends Aye> it = vec.iterator();
public boolean hasNext() { return it.hasNext(); }
public Aye next() { return it.next(); }
public void remove() { it.remove(); }
};
}
}

H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
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.5 (GNU/Linux)

iD8DBQFGJlESe+7xMGD3itQRAsr/AJ9kjiHDv4JJYKCoMLpyepa7xce+IwCcCyyA
jwD3UhMoDkP4V0N/JJtQXFk=
=w4TK
-----END PGP SIGNATURE-----
 
F

Frank Fredstone

Hendrik Maryns said:
Frank Fredstone schreef:

It’s not because it extends a wildcard capture that people will suddenly
be able to create instances of the interface or set anything. You allow
them to if you provide them the methods.

I can't sub-class a wildcard capture, so that makes it true that the
I said:
I suggest you read the Java generics document about wildcards once more.
They really aren’t evil.


Consider using ArrayList, see the thread Efficiency -- Vectors above.


private ArrayList<Aye> would suffice here, from what you do with it below.

Otherwise, what is your problem with using ArrayList<? extends Aye>
here? It is private anyway, so nobody can do anything with it.

If I take your meaning, it only changes where some assignments are put.

Either what I have already, or:

// or arraylists

private Vector<PrivateAye> realAyes;
private Vector<? extends PrivateAye> ayes;

public void go() throws Exception {
realAyes = new Vector<PrivateAye>();
realAyes.add(new PrivateVector("a", 0));
realAyes.add(new PrivateVector("b", 1));
ayes = realAyes;
}

And one line deleted from the iterator method:

public Iterator<Aye> iterator() {
return new Iterator<Aye>() {
private Iterator<? extends Aye> it = ayes.iterator();
public boolean hasNext() { return it.hasNext(); }
public Aye next() { return it.next(); }
public void remove() { it.remove(); }
};
}
You’ll have to explain what you need the PrivateAye class for, to make
the point clearer.

What I need PrivateAye for is to demonstrate a scenario where I need
to have an iterable of interfaces where the actual implementation is
private. I'm posing the scenario in order to ask the question:

Is there something, probably involving wildcards that would make it so
that I don't have to create an anonymous iterator class in my iterator
method of the iterable (where the iterable is of instances of
interfaces which are implemented by private classes).

None of these are answers to the question:

1. Don't do that.
2. Why are you doing that?
3. Use this instead.

Though those can be interesting too.

My motivation is to clear up what looks like it could be a gap in my
understanding of generics, not to have a solution given to me for some
immediately practical purpose.
 
L

Lew

Frank said:
Is there something, probably involving wildcards that would make it so
that I don't have to create an anonymous iterator class in my iterator
method of the iterable (where the iterable is of instances of
interfaces which are implemented by private classes).

You have received the same answer from several people. You might consider
accepting the advice.

The <? extends Aye> gives you the ability to directly use the collection's
iterator (Iterator<? extends Aye>) to manipulate instances of Aye that happen
to be PrivateAye, but no one using the Iterator can know that. The behavior
of each object accessed via the Iterator will be PrivateAye's behavior, as my
SSCCE upthread shows you, but the access will only be through a variable of
type Aye.

What of that fails to achieve what you want?
What I need PrivateAye for is to demonstrate a scenario where I need
to have an iterable of interfaces where the actual implementation is
private.

Does that, assuming by "private" you mean "not displayed to clients of the
Iterator".
I don't have to create an anonymous iterator class in my iterator
method of the iterable

Check. Just use the iterator of the collection directly, no anonymous
iterator class.
In the collection class I want to have a private implementation of
that interface.
Check.

I was hoping that I had missed some typical way, using wildcards, to get
Iterator<Aye> in my super-class of Iterable<Aye> from my backing
collection of PrivateAye objects, instead of having to write a special
case Iterator class to instantiate in the iterator method.

If you use Iterator<? extends Aye>, you get instances of Aye from the Iterator
that behave like PrivateAye, just like you want, without writing a special
Iterator class, just like you wanted.

I'm sorry, but I just don't see anything missing from what several people are
telling you. Why not try it?
 
F

Frank Fredstone

Lew said:
You have received the same answer from several people. You might
consider accepting the advice.

The <? extends Aye> gives you the ability to directly use the
collection's iterator (Iterator<? extends Aye>) to manipulate
instances of Aye that happen to be PrivateAye, but no one using the
Iterator can know that. The behavior of each object accessed via the
Iterator will be PrivateAye's behavior, as my SSCCE upthread shows
you, but the access will only be through a variable of type Aye.

What of that fails to achieve what you want?

As far as I can tell, it's not possible, unless this is an answer to a
different question than the one I've been asking. Given a class that
is an iterable collection of instances of an interface:

class X implements Iterable<Aye> { ... }

the iterator can't return Iterator <? extends Aye>, and this is not
legal:

class X implements Iterable<? extends Aye> { ... }

Frank
 
H

Hendrik Maryns

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

Frank Fredstone schreef:
As far as I can tell, it's not possible, unless this is an answer to a
different question than the one I've been asking. Given a class that
is an iterable collection of instances of an interface:

class X implements Iterable<Aye> { ... }

the iterator can't return Iterator <? extends Aye>, and this is not
legal:

class X implements Iterable<? extends Aye> { ... }

Well, now things are finally getting clearer: you gave the impression
you didn’t /want/ too use wildcards. Indeed in class declarations you
cannot use wildcards, but type parameters can be confined in exactly the
same way.

So what you need is

class X implements Iterable<T extends Aye> { ... }

H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
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.5 (GNU/Linux)

iD8DBQFGJzQXe+7xMGD3itQRAsC5AJ0Q2CjCQuasz5kNGo2IEiF86BbxEwCfdTyg
qgnHIRt+aeNuNJEsmvzdJ1s=
=9WMP
-----END PGP SIGNATURE-----
 
H

Hendrik Maryns

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

Frank Fredstone schreef:
As far as I can tell, it's not possible, unless this is an answer to a
different question than the one I've been asking. Given a class that
is an iterable collection of instances of an interface:

class X implements Iterable<Aye> { ... }

the iterator can't return Iterator <? extends Aye>, and this is not
legal:

class X implements Iterable<? extends Aye> { ... }

Okay, things are getting clearer now. You gave the impression you
didn’t want to use the joker. I didn’t find a good solution either.
The easiest I can come up with is the following:

import java.util.*;

interface Aye {
String aye();
}

class A {
private String a;

public A(String eh) {
a = eh;
}

String a() {
return a;
}
}

public class C implements Iterable<Aye> {

class PrivateAye extends A implements Aye {
private int code = 0;

public PrivateAye(String eh, int n) {
super(eh);
setCode(n);
}

public int getCode() {
return code;
}

public void setCode(int n) {
code = n;
}

public String aye() {
return a();
}
}

private ArrayList<PrivateAye> ayes;

public static void main(String[] args) throws Exception {
C x = new C();
x.go();
}

public void go() throws Exception {
ayes = new ArrayList<PrivateAye>();
ayes.add(new PrivateAye("a", 0));
ayes.add(new PrivateAye("b", 1));
for (Aye a : this) {
System.out.println(a.aye());
}
}

public Iterator<Aye> iterator() {
List<Aye> temp = new ArrayList<Aye>(ayes);
return temp.iterator();
// or even return new ArrayList<Aye>(ayes).iterator();
}
}

In this particular case, it is a but superfluous since Iterator does not
allow the addition of elements. But the extra step is necessary to
ensure type-safety.

H.
- --
Hendrik Maryns
http://tcl.sfs.uni-tuebingen.de/~hendrik/
==================
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.5 (GNU/Linux)

iD8DBQFGJzfBe+7xMGD3itQRAqATAJ0XUtRKiDGzSdeIZfBC53LOQqpqowCdEDdy
HjRUvY9MlmdEfl6MnIFMEyY=
=GCWT
-----END PGP SIGNATURE-----
 
P

Piotr Kobzda

Sure. As long as Java Generics is implemented by erasure, probably
simplest approach is to use raw-type cast:

public Iterator<Aye> iterator() {
return (Iterator)ayes.iterator();
}

And then either ignore compiler's warning, or suppress it using
appropriate annotation.


What's wrong though with that simple, and type-safe anonymous wrapper of
iterator there?

If you use it often, there is no problem in generalizing it with extra
helper class like that:

public class IteratorWrapper<E> implements Iterator<E> {
protected Iterator<? extends E> iterator;
public IteratorWrapper(Iterator<? extends E> iterator) {
this.iterator = iterator;
}
public boolean hasNext() { return iterator.hasNext(); }
public E next() { return iterator.next(); }
public void remove() { iterator.remove(); }
}

Then, every time you'll need to reduce declared type of iterator
elements, you'll simply do that with:

public Iterator<Aye> iterator() {
return new IteratorWrapper<Aye>(ayes.iterator());
}


piotr
 

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

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top