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