我有一个列表,我想使用流过滤,抓住前10个并向用户显示。按下按钮后。我想从该位置继续流。
List<MyObject> allResults = getResults();
allResults.stream()
.filter(this::someCrazyFiltering)
.limit(10)
.map(this::turnToDisplayItem)
.forEach(this::addDisplayItemToContainer);
// some stuff..
onClick(() -> {
List<MyObject> allResults = getResults();
allResults.stream()
.filter(this::someCrazyFiltering)
.skip(10) // will eventually be 10 * amount of times clicked.
.limit(10)
.map(this::turnToDisplayItem)
.forEach(this::addDisplayItemToContainer);
});
但是问题是,在这里,我必须在第一个10 上运行过滤器,其中许多人都不匹配过滤器(再次)。
到目前为止,我使用的一些解决方案是使用PEEK存储最后一项的索引,然后做一个(pre-skip)。
List<MyObject> allResults = getResults();
allResults.stream()
.filter(this::someCrazyFiltering)
.limit(10)
.peek(o -> this.storeIndex(o, allResults)) // This feels klunky
.map(this::turnToDisplayItem)
.forEach(this::addDisplayItemToContainer);
onClick(() -> {
List<MyObject> allResults = getResults();
allResults.stream()
.skip(this.storedIndexToSkip) // This being stored from storeIndex function above.
.filter(this::someCrazyFiltering)
.limit(10)
.peek(o -> this.storeIndex(o, allResults)) // Store again for next click; This STILL feels klunky
.map(this::turnToDisplayItem)
.forEach(this::addDisplayItemToContainer);
});
我知道流中没有"索引"之类的东西,因此我需要在storeIndex
函数中执行allResults.indexOf(o)
,(然后是不同的项目)
但是,如果有人能想到更好的机制吗?就像能够在filter
/limit
??
或者只是一起忽略流,然后返回到良好的旧for-each循环并在发现10后存储i
?
欢迎任何建议。
您可以将流转换为迭代器,并致电Next()10次。迭代器将在每个下一个()呼叫上评估懒惰。
List<MyObject> allResults = getResults();
Iterator<DisplayItem> it = allResults.stream()
.filter(this::someCrazyFiltering)
.map(this::turnToDisplayItem)
.iterator();
onClick(() -> {
int n = 0;
while(n < 10 && it.hasNext()){
this.addDisplayItemToContainer(it.next());
}
});