javalistjava-stream

Find the last element matching an expensive condition from a List, using Stream


I have an ordered List of roughly one million elements of which I'm looking for the last element that matches a specific condition, but the condition is heavy to compute so it's better if I start from the end instead. There are always roughly log(n) matching elements, with a minimum of 1.

I can do it manually:

List<Element> elements = ...;
Element element = null;
for (var it = elements.listIterator(elements.size()); it.hasPrevious(); ) {
  var candidate = it.previous();
  if (heavyConditionPredicate.test(candidate)) {
    element = candidate;
    break;
  }
}

Is there any way to write this using Streams, so that the heavyConditionPredicate is not tested against each element of the list? If the heavyConditionPredicate would not have been so heavy to compute, I'd have used alternative means, but I'm not that lucky.

Note that elements can be any type of List, and the one I get doesn't necessarily implements RandomAccess, so accessing the list by their index might be costly as well.


Solution

  • Guava's Lists::reverse definitely helps here, as it's a view and it doesn't modify my list and it doesn't access elements by their index:

    Lists.reverse(elements).stream()
      .filter(heavyConditionPredicate)
      .findFirst();