Predicate based method of Java 8 stream indexof
See English answers > stream way to get index of first element matching Boolean
int index = list.stream().indexOf(e -> "TESTNAME".equals(e.getName()));
But it didn't help Of course, I can write like this:
int index = list.indexOf(list.stream().filter(e -> "TESTNAME".equals(e.getName()))
.findFirst().get());
But this will a) iterate the list twice (in the worst case, the element will be the last) and b) fail if there is no element matching predicate (I prefer - 1 Index)
I have written a utility method for this function:
public static <T> int indexOf(List<T> list,Predicate<? super T> predicate) {
int idx = 0;
for (Iterator<T> iter = list.iterator(); iter.hasNext(); idx++) {
if (predicate.test(iter.next())) {
return idx;
}
}
return -1;
}
However, since this seems to be a very simple algorithm, I expected it somewhere in the Java 8 stream API I just miss it, or does it really have no such function? (additional question: if there is no such method, is there a good reason? Is it possible that using indexes in functional programming is an anti pattern?)
Solution
Your loop is good, 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 similar stream
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 if the list is large instead of random access, it will become quiet and inefficient I'll stay in the loop
