Addition of Predicate-based findIndex and findLastIndex methods to java.util.List

Remi Forax forax at univ-mlv.fr
Fri Apr 19 17:47:21 UTC 2024


Hello, 
for me, it seems what you want is Collector on Stream which is able to short-circuit, 
so you can write 
list.stream().collect(Collectors.findFirst(s -> s.contains("o"))) 
and in reverse 
list.reversed().stream().collect(Collectors.findFirst(s -> s.contains("o"))) 

Using a Stream here is more general and will work with other collections like a LinkedHashSet for example. 
Sadly, there is no way to define a short-circuiting collector :( 

You can have a short-circuiting Gatherer like this 
<T> Gatherer<T, ?, Integer> findIndex(Predicate<? super T> predicate) { 
return Gatherer.ofSequential( 
() -> new Object() { int index; }, 
Integrtor.ofGreedy((state, element, downstream) -> { 
var index = state.index++; 
if (predicate.test(element)) { 
return downstream.push(index); 
} 
return true; 
})); 
} 

and use it like this: 
list.stream().gather(findIndex(s -> s.contains("o"))).findFirst().orElse(-1); 

But it's more verbose. 

I wonder if at the same time that the Gatherer API is introduced, the Collector API should be enhanced to support short-circuiting collectors ? 

regards, 
Rémi 

> From: "ІП-24 Олександр Ротань" <rotan.olexandr at gmail.com>
> To: "core-libs-dev" <core-libs-dev at openjdk.org>
> Sent: Friday, April 19, 2024 5:59:39 PM
> Subject: Addition of Predicate-based findIndex and findLastIndex methods to
> java.util.List

> Subject
> Addition of Predicate-based findIndex and findLastIndex 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.

> Here I want to propose methods that 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.

> The changes I am proposing are implemented in this PR: [
> https://github.com/openjdk/jdk/pull/18639 |
> https://github.com/openjdk/jdk/pull/18639 ] . Here is a brief overview of the
> changes made in this pull request:

> Added the findIndex (Predicate<? super E> filter) method to the List interface.
> Added the findLastIndex (Predicate<? super E> filter) method to the List
> interface.
> Implemented these methods in all non-abstract classes that implement the List
> interface, as well as List itself (default impl).
> 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.findIndex(s -> s.contains("ct t"));
> System.out.println(index1); // Expected output: 1
> int index2 = list. findLastIndex(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
> Or other approaches that require additional instructions and, therefore, can`t
> be used in all scopes (like passing argument to method).

> 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 based
> on your suggestions.

> The main reason I am publishing this proposal in the mailing system is to gather
> feedback from the Java developers community, especially about possible caveats
> related to backward compatibility of your projects. Would appreciate every
> opinion!

> Best regards
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20240419/58dfc53a/attachment-0001.htm>


More information about the core-libs-dev mailing list