Java8 Stream : Collect elements after a condition is met

Viewed 10695

My POJO is as follows

class EventUser {
  private id;
  private userId;
  private eventId;
}

I retrieve EventUser object as follows:

List<EventUser> eventUsers = eventUserRepository.findByUserId(userId);

Say the 'eventUsers' is as follows:

[
{"id":"id200","userId":"001","eventId":"1010"},
{"id":"id101","userId":"001","eventId":"4212"},
{"id":"id402","userId":"001","eventId":"1221"},
{"id":"id301","userId":"001","eventId":"2423"},
{"id":"id701","userId":"001","eventId":"5423"},
{"id":"id601","userId":"001","eventId":"7423"}
]

Using streaming, and without using any intermediate variable , how can I filter and collect events after a given EventUser.id: ex:

List<EventUser> filteredByOffSet = eventUsers.stream.SOMEFILTER_AND_COLLECT("id301");

the result should be :

[{"id":"id301","userId":"001","eventId":"2423"},
{"id":"id701","userId":"001","eventId":"5423"},
{"id":"id601","userId":"001","eventId":"7423"}]
4 Answers

In Java 8 you need a stateful filter

public static <T> Predicate<T> from(Predicate<T> test) {
    boolean[] found = { false };
    // once found, always true
    return t -> found[0] || (found[0] = test.test(t));
}

NOTE: this only makes sense for single threaded streams.

List<EventUser> filteredByOffSet = 
     eventUsers.stream()
               .filter(from(e -> "id301".equals(e.getId()))
               .collect(Collectors.toList());

Find the index of the search item first:

int asInt = IntStream.range(0, list.size())
    .filter(userInd-> list.get(userInd).equals(<criteria>))
    .findFirst()
    .getAsInt();

Get items on and after the index:

list.stream().skip(asInt).collect(Collectors.toList());

You cant do that without using any intermediate variables. finding the position and iterate it to the end (see this question below that answer it more precisely) enter link description here

Related