Supplier <Stream> 产生空流,但作为列表,它不是空的

Supplier <Stream> yields empty stream, but as a list, it's not empty

在我的代码中,我不得不多次遍历一堆类型为 T 的对象。由于某些对象可能非常大,我使用 SupplierStream<T> 而不是将它们全部收集在列表或集合中。方法如下:

private static Supplier<Stream<T>> streamSupplier(...) {
    Iterator<T> iterator = ...;
    Iterable<T> iterable = () -> iterator;
    return () -> StreamSupport.stream(iterable.spliterator(), false);
}

以及代码中的其他地方

Supplier<Stream<T>> supplier = streamSupplier(...);
List<T> ts = supplier.get().collect(Collectors.toList());
return ts.isEmpty(); // <-- true

问题是当我通过上述方法调用return供应商的Supplier#get()方法时,它总是是空的。但是当我将代码更改为 return 列表时,一切正常:

private static List<T> listSupplier(...) {
    Iterator<T> iterator = ...;
    Iterable<T> iterable = () -> iterator;
    List<T> ts = Lists.newArrayList(iterable);
    return ts; // <-- is populated correctly, NOT empty
}

我认为如果我想重复使用一个流(这样我就不会以关闭的`Stream 结束),使用 Supplier 是正确的方法。我做错了什么?

您似乎正试图从同一个迭代器创建多个流。

试试这个:

Iterable<Document> docIterable = () -> ...;

... 来自 Iterator<Document> docIterator = ...;

此外,您为什么要返回 Supplier<Stream<Document>> 而不是 Stream<Document>

你可能想做这样的事情:

private static Supplier<Stream<T>> streamSupplier(...) {
    return () -> {
        Iterator<T> iterator = ...;
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
    };
}

这假设行

Iterator<T> iterator = ...;

每次都创建一个新的迭代器,独立于任何现有的迭代器。

另请注意,您应该调整创建 Spliterator 的方式,例如,如果大小已知,或者是否存在重要的特征(例如顺序)。

最后,做事一定要小心

Iterable<T> iterable = () -> iterator;

这几乎是一种反模式。虽然它在类型系统中工作——调用生成的 Iterable 的 iterator() 方法将 return Iterator 的一个实例——但它通常不会工作。原因是大多数使用 Iterable 实例的代码都假定它可以多次调用 iterator() 并获得独立的迭代器。这不会那样做;它每次捕获 Iterator 和 returns same Iterator 实例。这将导致与您所看到的类似的奇怪破损。