Java 8 Stream indexOf method based on predicate

Your loop is not bad, but you can simplify it:

public static <T> int indexOf(List<T> list, Predicate<? super T> predicate) {
    for(ListIterator<T> iter = list.listIterator(); iter.hasNext(); )
        if(predicate.test(iter.next())) return iter.previousIndex();
    return -1;
}

You can use a stream like

public static <T> int indexOf(List<T> list, Predicate<? super T> predicate) {
    return IntStream.range(0, list.size())
        .filter(ix -> predicate.test(list.get(ix)))
        .findFirst().orElse(-1);
}

but this will become quite inefficient if the list is large and not random access. I’d stay with the loop.


Starting with Java 9, there’s the alternative

public static <T> int indexOf(List<T> list, Predicate<? super T> predicate) {
    long noMatchPrefix = list.stream().takeWhile(predicate.negate()).count();
    return noMatchPrefix == list.size()? -1: (int) noMatchPrefix;
}

which is really expressive regarding the task “count the elements up to the first match”, but is not exactly the same as “get the index of the first matching element”, which shows when there is no match, so we need to replace the result with -1 then.