RFR: 8329760: Add indexOf(Predicate<? super E> filter) to java..util.List interface

Evemose duke at openjdk.org
Thu Apr 18 22:00:14 UTC 2024


On Fri, 5 Apr 2024 00:31:22 GMT, Evemose <duke at openjdk.org> wrote:

>> **Subject**
>> Addition of Predicate-based `indexOf` and `lastIndexOf` methods to `java.util.List`
>> 
>> **Motivation**
>> The motivation behind this proposal is to enhance the functionality of the `List` interface by providing a more flexible way to find the index of an element. Currently, the `indexOf` and `lastIndexOf` methods only accept an object as a parameter. This limits the flexibility of these methods as they can only find the index of exact object matches.
>> 
>> The proposed methods would accept a `Predicate` as a parameter, allowing users to define a condition that the desired element must meet. This would provide a more flexible and powerful way to find the index of an element in a list.
>> 
>> Here is a brief overview of the changes made in this pull request:
>> 
>> 1. Added the `indexOf(Predicate<? super E> filter)` method to the `List` interface.
>> 2. Added the `lastIndexOf(Predicate<? super E> filter)` method to the `List` interface.
>> 3. Implemented these methods in all non-abstract classes that implement the `List` interface.
>> 
>> The changes have been thoroughly tested to ensure they work as expected and do not introduce any regressions. The test cases cover a variety of scenarios to ensure the robustness of the implementation.
>> 
>> For example, consider the following test case:
>> 
>> List<String> list = new ArrayList<>();
>> list.add("Object one");
>> list.add("NotObject two");
>> list.add("NotObject three");
>> 
>> int index1 = list.indexOf(s -> s.contains("ct t"));
>> System.out.println(index1); // Expected output: 1
>> int index2 = list.lastIndexOf(s -> s.startsWith("NotObject"));
>> System.out.println(index2); // Expected output: 2
>> 
>> 
>> Currently, to achieve the same result, we would have to use a more verbose approach:
>> 
>> int index1 = IntStream.range(0, list.size())
>>                      .filter(i -> list.get(i).contains("ct t"))
>>                      .findFirst()
>>                      .orElse(-1);
>> System.out.println(index1); // Output: 1
>> int index2 = IntStream.range(0, list.size())
>>                          .filter(i -> list.get(i).startsWith("NotObject"))
>>                          .reduce((first, second) -> second)
>>                          .orElse(-1);
>> System.out.println(index2); // Output: 2
>> 
>> 
>> I believe these additions would greatly enhance the functionality and flexibility of the `List` interface, making it more powerful and user-friendly. I look forward to your feedback and am open to making any necessary changes bas...
>
> side note: looks like this code have been reformated and some unused imports has been reformated. jdk compiles and works just fine, so i guess its not a big deal

> Hello @Evemose, if we add an API we should also consider if implementation can efficiently implement it. How is this new API better than using a ListIterator directly so it's worth the additional methods?

Hi, @liach ! The implementations i provided in this pull requests are pretty much imitating behaviour of indexOf(Object). Every class that has overriden indexOf(Object) recieved implementation of indexOf(Predicate) that works the same way except for search is based on predicate and not equality. Therefore, the effectiveness of implementation is straight up depends on effectiveness of indexOf(Object) for each separate java.util.List impl.

As for ListIterator, where suitable, it has already been used in implementations in classes where it was considered suitable for indexOf(Object) (to be more precise, in AbstractList). The main goal of this pull requst is to provide shorthand for developers as search for index of element that match predicate is very common task and providing way to do it as comfortable as possible should vastly enhance development expirience.

For ListIterator specifically: the main downside of its direct usage for developer is inability to use it fluently (as method call argument, for example), which forces to either implement method to find index separately or find it in same method as invocation but before invocation explicitly. Both cases are pretty frustraiting and, in my opinion, shouldn`t be neccessary for high-level language like Java.

Summarizing, its not that in current stdlib there are no ways to search for index of element based on condition, but this addition would be a great way to make Java development more comfortable and fast.

PS:
Also implementing indexOf with predicate is a common practice for many high level languages: C#/.NET has FindIndex, Kotlin has indexOfFirst, Swift has firstIndex etc.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/18639#issuecomment-2040025647


More information about the core-libs-dev mailing list