Reputation: 1664
I have a list, I would like to filter using stream, grab the first 10, and display to user. After a button press.. I would like to continue the stream from that location.
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);
});
But the problem is, here I am having to run the filter on the first 10 + how ever many do not match the filter (again).
So far, a few solutions I have is using peek to store the index of the last item, and do a (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);
});
I know there is no such thing as an "index" in a stream, So I would need to do allResults.indexOf(o)
inside the storeIndex
function, (then will be distinct items)
but if anyone can think of a better mechanism for this? Like being able to splinter off a stream after the filter
/limit
??
Or just ignoring streams all together and just going back to good old for-each loop and storing i
once 10 have been found?
Any suggestions welcome.
Upvotes: 0
Views: 1495
Reputation: 2110
You could transform your stream to an iterator and call next() 10 times. The Iterator will get evaluated lazy on each next() call.
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());
}
});
Upvotes: 2