我有一个列表,我想使用流过滤,抓住前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来存储最后一项的索引,并执行(预跳过)。
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);
});
我知道流中没有“索引”这样的东西,所以我需要在allResults.indexOf(o)
函数中进行storeIndex
,(然后将是不同的项目)
但是,如果有人能想到更好的机制吗?就像能够在filter
/ limit
??
或者只是忽略所有流,然后回到旧的for-each循环并在找到10之后存储i
?
欢迎任何建议。
答案 0 :(得分:2)
您可以将流转换为迭代器并调用next()10次。 Iterator将在每次next()调用时得到延迟评估。
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());
}
});