WORMSS
WORMSS

Reputation: 1664

Continue java stream after collection

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

Answers (1)

Michael A. Schaffrath
Michael A. Schaffrath

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

Related Questions