I have a list of map entries, and I need an iterable that returns the keys.

Of course, we could be naive and copy over into a new collection of the desired type, but that's inefficient.

So let's see if we can provide a view of the existing structure using generics. Yes, I was able to do that, but it's not perfect: it gives unchecked conversions when it's passed to a function expecting Iterable<K>. Could it be improved to avoid these warnings?

Perhaps it could implement Iterable<K> similar to the commented out line which is the path I attempted but couldn't complete. Can you figure out the similar but correct (no warnings on usage) generic implementation?

This should help demonstrate how the ListKeyIterable is used:

List&LT; Map.Entry &LT; Long,String &GT; &GT; list;

void traverse( Iterable&LT;Long&GT; ) {}

traverse( new ListKeyIterable&LT;List&LT;Map.Entry&LT;Long,String&GT;&GT;&GT;( list );

Here is the working code, but it gives unchecked conversion warning on the call to traverse().

class ListKeyIterable&LT;T extends List&LT;? extends Map.Entry&LT;?,?&GT;&GT;&GT; implements Iterable
//class ListKeyIterable&LT;T extends List&LT;? extends Map.Entry&LT;K,?&GT;&GT;&GT; implements Iterable&LT;K&GT;
    T list;

    public ListKeyIterable( T list ) { this.list = list; }

    class ListKeyIterator&LT;K&GT; implements Iterator&LT;K&GT; {
        Iterator&LT;Map.Entry&LT;K,?&GT;&GT; iterator;

        public ListKeyIterator( Iterator&LT;Map.Entry&LT;K,?&GT;&GT; iterator ) { this.iterator = iterator; }
        @Override public boolean hasNext() { return iterator.hasNext(); }
        @Override public K next() { return iterator.next().getKey(); }
        @Override public void remove() { throw new RuntimeException( "ValueListIterator remove() not implemented." ); }

    @Override public Iterator iterator() { return new ListKeyIterator( list.iterator() ); }
    //@Override public &LT;K&GT; Iterator&LT;K&GT; iterator() { return new ListKeyIterator( list.iterator() ); }

Just parameterize with both types:

class ListKeyIterable<K,T extends List<? extends Map.Entry<K,?>>> implements Iterable<K>;
| improve this answer | |
  • \$\begingroup\$ Yes, that's the ticket. Caller needs to of course specify both now: traverse( new ListKeyIterable<Long,List<Map.Entry<Long,String>>>( list ); \$\endgroup\$ – user3119 Apr 5 '11 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy