Addition of Predicate-based findIndex and findLastIndex methods to java.util.List
David Alayachew
davidalayachew at gmail.com
Fri Apr 19 21:11:47 UTC 2024
Hello
Thanks for sending this email. Your idea makes a lot of sense, but I feel
that it only serves a very specific use case. That does not make it bad,
but it does make it narrow.
I already suggested my idea in my email to Rémi, where the index is just
another field in the data type being streamed. Doing it this way, we can
not only cover your use case, but the use cases of many others. It has a
far wider reach for the same level of effort.
And finally, make it a point to send an email on the mailing list and
getting consensus BEFORE making a pull request. I am guilty of this too.
But going out of order like this slows down the system and forces reviewers
to take extra steps that they wouldn't have to if you had followed protocol.
On Fri, Apr 19, 2024 at 5:02 PM David Alayachew <davidalayachew at gmail.com>
wrote:
>
> No Rémi, I don't think your idea is the right approach. You are working on
> the wrong level of abstraction.
>
> Many users ask requests like this all the time, and what you are
> suggesting would be even more error-prone than the equivalent for loop or the
> IntStream suggestion that the user above requested. Not to mention that
> getting it to parallelize would be a task many users are likely to mess up
> -- either in correctness or in performance.
>
> I think you would get far more mileage from adding 2 methods on the list
> interface streamWithIndex() and parallelStreamWithIndex() that would return
> a Stream<WithIndex<T>>, as opposed to just Stream<T>.
>
> That way, users are not writing a custom Gatherer each time they want to
> work with the index. They just have the index be a field in the object.
> They can work with it the same way they would any other object field.
>
> Furthermore, doing it this way makes the correct answer obvious. If I need
> to do something with an index, stream with the index.
>
> On top of that, it significantly enhances readability by making it clear
> to the reader that, whatever this stream is doing will require use of the
> index, so watch out for that.
>
>
>
> On Fri, Apr 19, 2024, 1:47 PM Remi Forax <forax at univ-mlv.fr> wrote:
>
>> 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. 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/5c6d1dc5/attachment-0001.htm>
More information about the core-libs-dev
mailing list