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