我有一个现有的界面,该界面使我可以访问如下所示的理论上无限的集合:
List<Element> retrieve(int start, int end);
//example
retrieve(5, 10); // retrieves the elements 5 through 10.
现在,我想在此现有接口之上构建Java流,这样我就可以流式传输所需数量的元素,而无需立即请求大列表。
我将如何去做?
我查看了Java流的示例,发现的所有示例都是如何从完全在内存中的集合创建流的示例。我目前一次加载30个元素,并进行必要的处理,但是如果我可以抽象出该逻辑并返回一个流,那会更干净。
答案 0 :(得分:2)
class Chunk implements Supplier<Element> {
private final Generator generator;
private final int chunkSize;
private List<Element> list = Collections.emptyList();
private int index = 0;
public Chunk(Generator generator, int chunkSize) {
assert chunkSize > 0;
this.generator = generator;
this.chunkSize = chunkSize;
}
@Override
public Element get() {
if (list.isEmpty()) {
list = generator.retrieve(index, index + chunkSize);
index += chunkSize;
}
return list.remove(0);
}
}
在这里,我假设retrieve
返回一个可变列表。如果没有,那么此时您需要创建一个新的ArrayList
或等效的文件。
这可以用作Stream.generate(new Chuck(generator, 30))
。它会生成一个从索引0开始的无限流。您可以添加一个构造函数,以便在有用的情况下设置起始索引。
答案 1 :(得分:1)
我认为您无法编辑retrieve
方法。
您可以这样做:
IntStream.iterate(1, x -> x + 1).mapToObj(x -> retrieve(x, x).get(0))
如果序列中的一项取决于上一项,那么这意味着您需要重新计算第n
条,直到第n
条为止。
这可以通过以100为块的方式稍微解决该问题:
IntStream.iterate(1, x -> x + 1).mapToObj(x -> retrieve(1 + (x - 1) * 100, x * 100)).flatMap(List::stream)
如果您可以编辑该界面后面的内容,则可以使用上述Stream<Element>
使其返回IntStream.iterate
。