Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / April 2007

Tip: Looking for answers? Try searching our database.

iterator over superclass of collection

Thread view: 
Frank Fredstone - 17 Apr 2007 22:22 GMT
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(); }
       };
   }
}
Tom Hawtin - 17 Apr 2007 23:36 GMT
> 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.

I guess you could just use Iterator<? extends Aye> and Iterable<?
extends Aye>.

>     public Iterator<Aye> iterator() {
>         return new Iterator<Aye>() {
[quoted text clipped - 5 lines]
>         };
>     }

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
Frank Fredstone - 18 Apr 2007 02:47 GMT
>> 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.
>
> 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

>>     public Iterator<Aye> iterator() {
>>         return new Iterator<Aye>() {
[quoted text clipped - 26 lines]
>
> Tom Hawtin
Tom Hawtin - 18 Apr 2007 03:18 GMT
>>> I want to expose an iterator over a collection, where the iterator
>>> returns elements that are a super class of the actual
[quoted text clipped - 4 lines]
> 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
Frank Fredstone - 18 Apr 2007 04:28 GMT
>>>> I want to expose an iterator over a collection, where the iterator
>>>> returns elements that are a super class of the actual
[quoted text clipped - 10 lines]
>         return ayes.iterator();
>     }

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

>> In your more generic vresion doesn't the final make the code not
>> thread safe?
[quoted text clipped - 6 lines]
> 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.
Lew - 18 Apr 2007 04:46 GMT
Tom Hawtin <usenet@tackline.plus.com> writes:
>> 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<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>

Signature

Lew

Chris Smith - 18 Apr 2007 15:33 GMT
> > I mean just use the iterator straight from the vector:
> >
[quoted text clipped - 3 lines]
>
> 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>.

Signature

Chris Smith

Frank Fredstone - 18 Apr 2007 17:10 GMT
>> > I mean just use the iterator straight from the vector:
>> >
[quoted text clipped - 8 lines]
> 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(); }
       };
   }
}
Hendrik Maryns - 18 Apr 2007 18:10 GMT
Frank Fredstone schreef:

>>>> I mean just use the iterator straight from the vector:
>>>>
[quoted text clipped - 16 lines]
> 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 {
[quoted text clipped - 9 lines]
>
>     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();
[quoted text clipped - 20 lines]
>     }
> }

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
Frank Fredstone - 18 Apr 2007 20:06 GMT
> Frank Fredstone schreef:
>>
[quoted text clipped - 22 lines]
> 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
iterator method of the Iterable can't be Iterator<? extends Aye>, I
think.

>> 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
[quoted text clipped - 28 lines]
> 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.
Lew - 19 Apr 2007 00:38 GMT
> 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?

Signature

Lew

Frank Fredstone - 19 Apr 2007 05:01 GMT
>> 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
[quoted text clipped - 12 lines]
>
> 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

>> What I need PrivateAye for is to demonstrate a scenario where I need
>> to have an iterable of interfaces where the actual implementation is
[quoted text clipped - 25 lines]
> I'm sorry, but I just don't see anything missing from what several
> people are telling you.  Why not try it?
Hendrik Maryns - 19 Apr 2007 10:19 GMT
Frank Fredstone schreef:

>>> 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
[quoted text clipped - 22 lines]
>
> 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
Hendrik Maryns - 19 Apr 2007 10:34 GMT
Frank Fredstone schreef:

>>> 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
[quoted text clipped - 22 lines]
>
> 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
Piotr Kobzda - 19 Apr 2007 11:39 GMT
>>> 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).

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
Daniel Pitts - 18 Apr 2007 01:10 GMT
> I want to expose an iterator over a collection, where the iterator
> returns elements that are a super class of the actual
[quoted text clipped - 65 lines]
>
> }

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!


Free Magazines

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

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.