Java:如何将集合从 Apache commons collection4 lib 传递给 chainedIterator(Collection<Iterator<? extends E>> iterators)?

问题描述

我在下面的代码中尝试使用 chainedIterator(Collection<Iterator<? extends E>> iterators)(Apache commons collection4 lib)中的 org.apache.commons.collections4.IteratorUtils,但出现编译时错误

这是我的代码..

private Iterator<Resource> getResources() {
        String[] paths = getParameterValues();
        Collection<Iterator<Resource>> its = new ArrayList<Iterator<Resource>>();       
        for (int i = 0; i < paths.length; i++) {
            String path = paths[i];         
            its.add(getonlyResource(path));
        }
        return IteratorUtils.chainedIterator(its); //gives compile error - The method chainedIterator(Iterator<? extends E>...) in the type IteratorUtils is not applicable for the arguments (Collection<Iterator<Resource>>)
    }

解决方法

问题在于方法签名

public static <E> Iterator<E>
    chainedIterator(Collection<Iterator<? extends E>> iterators)

这太严格了。

它说要返回一个 Iterator<Resource>,你必须传入一个 Collection<Iterator<? extends Resource>>

反映实际意图的方法签名必须是

public static <E> Iterator<E>
    chainedIterator(Collection<? extends Iterator<? extends E>> iterators)

然后,您的代码将无误地编译,并且可以证明可以使用宽松的签名来实现该方法,例如

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();
}

另见How to convert an iterator to a stream?


但是您可以通过准确提供当前方法签名的要求来解决当前方法签名的问题。只需更改声明

Collection<Iterator<Resource>> its = new ArrayList<Iterator<Resource>>();

Collection<Iterator<? extends Resource>> its = new ArrayList<>();

然后,您可以按原样使用 IteratorUtils。但请注意,您根本不需要第 3 方库。整个方法只能使用内置功能来实现,例如

private Iterator<Resource> getResources() {
    return Arrays.stream(getParameterValues())
        .map(path -> getOnlyResource(path))
        .flatMap(it -> StreamSupport.stream(
            Spliterators.spliteratorUnknownSize(it,false))
        .iterator();
}

这类似于上面的示例 chainedIterator 实现,但不需要首先将迭代器收集到集合中的步骤。相反,它是惰性的,所以如果调用者没有遍历所有元素,这个解决方案甚至可能会跳过不必要的 getOnlyResource 调用。