The problem is the method signature
public static <E> Iterator<E>
chainedIterator(Collection<Iterator<? extends E>> iterators)
which is too restrictive.
It says that to return an Iterator<Resource>
you have to pass in a Collection<Iterator<? extends Resource>>
.
The method signature reflecting the actual intention has to be
public static <E> Iterator<E>
chainedIterator(Collection<? extends Iterator<? extends E>> iterators)
Then, your code would compile without error and it can be shown that implementing the method with that relaxed signature is possible, e.g.
public static <E> Iterator<E>
chainedIterator(Collection<? extends Iterator<? extends E>> iterators) {
if(iterators.isEmpty()) return Collections.emptyIterator();
return iterators.stream()
.flatMap(it -> StreamSupport.stream(
Spliterators.<E>spliteratorUnknownSize(it, Spliterator.ORDERED), false))
.iterator();
}
See also How to convert an iterator to a stream?
But you can work-around the problem of the current method signature by providing exactly what it demands. Just change the declaration
Collection<Iterator<Resource>> its = new ArrayList<Iterator<Resource>>();
to
Collection<Iterator<? extends Resource>> its = new ArrayList<>();
Then, you can use the IteratorUtils
as-is. But mind that you don’t need a 3rd party library at all. The entire method can be implemented using built-in features only like
private Iterator<Resource> getResources() {
return Arrays.stream(getParameterValues())
.map(path -> getOnlyResource(path))
.flatMap(it -> StreamSupport.stream(
Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false))
.iterator();
}
This is similar to the example chainedIterator
implementation above, but does not require the step of first collecting the iterators into a collection. Instead, it’s lazy, so if the caller doesn’t iterate over all elements, this solution might even skip unnecessary getOnlyResource
calls.