Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any Java standard classes that implement Iterable without implementing Collection?

Tags:

I have a conundrum that's caused me to ponder whether there are any standard java classes that implement Iterable<T> without also implementing Collection<T>. I'm implementing one interface that requires me to define a method that accepts an Iterable<T>, but the object I'm using to back this method requires a Collection<T>.

This has me doing some really kludgy feeling code that give some unchecked warnings when compiled.

public ImmutableMap<Integer, Optional<Site>> loadAll(         Iterable<? extends Integer> keys ) throws Exception {     Collection<Integer> _keys;     if (keys instanceof Collection) {         _keys = (Collection<Integer>) keys;     } else {         _keys = Lists.newArrayList(keys);     }      final List<Site> sitesById = siteDBDao.getSitesById(_keys);     // snip: convert the list to a map 

Changing my resulting collection to use the more generified Collection<? extends Integer> type doesn't eliminate the unchecked warning for that line. Also, I can't change the method signature to accept a Collection instead of an Iterable because then it's no longer overriding the super method and won't get called when needed.

There doesn't seem to be a way around this cast-or-copy problem: other questions have been asked here an elsewhere and it seems deeply rooted in Java's generic and type erasure systems. But I'm asking instead if there ever are any classes that can implement Iterable<T> that don't also implement Collection<T>? I've taken a look through the Iterable JavaDoc and certainly everything I expect to be passed to my interface will actually be a collection. I'd like to use an in-the-wild, pre-written class instead as that seems much more likely to actually be passed as a parameter and would make the unit test that much more valuable.

I'm certain the cast-or-copy bit I've written works with the types I'm using it for in my project due to some unit tests I'm writing. But I'd like to write a unit test for some input that is an iterable yet isn't a collection and so far all I've been able to come up with is implementing a dummy-test class implementation myself.


For the curious, the method I'm implementing is Guava's CacheLoader<K, V>.loadAll(Iterable<? extends K> keys) and the backing method is a JDBI instantiated data-access object, which requires a collection to be used as the parameter type for the @BindIn interface. I think I'm correct in thinking this is tangental to the question, but just in case anyone wants to try lateral thinking on my problem. I'm aware I could just fork the JDBI project and rewrite the @BindIn annotation to accept an iterable...

like image 813
Patrick M Avatar asked Sep 14 '15 17:09

Patrick M


People also ask

Do all collections implement Iterable?

The Collection interface extends Iterable , so all subtypes of Collection also implement the Iterable interface.

Are all Java collections iterable?

Iterable is one of the main interfaces of the collection classes in Java. The Collection interface extends Iterable and hence all child classes of Collection also implement Iterable.

Does collections class implement Iterable interface?

There are three ways in which elements can be iterated in Java, using enhanced for loop, forEach() method and by calling iterator() method. The Collection interface extends the Iterable interface thus, all the classes implementing the Collection interface are iterable.

Does ArrayList implement Iterable?

ArrayList implements the Iterable interface. iterator() is the only method in this interface. Several classes in the Java libraries implement the Iterator<E> interface. Some of these classes are complicated, and a simple loop can't be used to access all their elements.


2 Answers

Although there is no class that would immediately suit your needs and be intuitive to the readers of your test code, you can easily create your own anonymous class that is easy to understand:

static Iterable<Integer> range(final int from, final int to) {     return new Iterable<Integer>() {         public Iterator<Integer> iterator() {             return new Iterator<Integer>() {                 int current = from;                 public boolean hasNext() { return current < to; }                 public Integer next() {                     if (!hasNext()) { throw new NoSuchElementException(); }                     return current++;                 }                 public void remove() { /*Optional; not implemented.*/ }             };         }     }; } 

Demo.

This implementation is anonymous, and it does not implement Collection<Integer>. On the other hand, it produces a non-empty enumerable sequence of integers, which you can fully control.

like image 101
Sergey Kalinichenko Avatar answered Nov 04 '22 17:11

Sergey Kalinichenko


To answer the question as per title:

Are there any Java standard classes that implement Iterable without implementing Collection?

From text:

If there ever are any classes that can implement Iterable<T> that don't also implement Collection<T>?

Answer:

Yes

See the following javadoc page: https://docs.oracle.com/javase/8/docs/api/java/lang/class-use/Iterable.html

Any section that says Classes in XXX that implement Iterable, will list Java standard classes implementing the interface. Many of those don't implement Collection.

like image 25
Andreas Avatar answered Nov 04 '22 18:11

Andreas