Did this discussion get lost? On Sun, Sep 20, 2020 at 1:27 AM Nir Lisker <nlis...@gmail.com> wrote:
> While it might not be difficult to add a find() method to Iterable, why >> limit it to >> the find operation, and what about all the other operations available on >> Stream? > > > Good question. I would say it's a matter of how much it is used and what > it takes to implement it. The find operation is a lot more common than > reduce from what I observe, for example, so I wouldn't suggest reduce to be > added..A map(Function<T,R>) operation would require creating a new > collection/iterable internally, and that can be messy (you could > preemptively create and pass your own, but then I doubt the worthiness of > it). forEach already exists. I just don't see anything enticing. > > Maybe what's necessary is a way to convert an Iterable to a Stream. > > > Most Iterables are Collections and arrays, and these are easy to convert, > so I'm not sure if that really helps. Besides,the idea is to avoid Stream, > as I've mentioned, due to the cumbersomeness and the overhead of creating a > stream. If I need to do > > iterable.stream().filter(person -> person.id == 123456).findAny/First() > > then I didn't really solve my problem. > > On the other hand, your examples use a list. The List interface already >> has methods >> indexOf/lastIndexOf which search the list for a particular object that's >> compared >> using equals(). It seems reasonable to consider similar methods that take >> a >> predicate instead of an object. > > > I could have used a Set just as well. As for indexOf(Predicate<T>), I > would say that it is useful (but personally, I hardly ever need the index > of an object, I need the object itself). Interestingly, > removeIf(Predicate<T>) exists, but remove(Predicate<T>) doesn't. I would > think twice before suggesting to add it though. > > Ultimately, you have access to a lot of analytics and codebase scans. If > you know which patterns are used a lot more than others it would be a good > guide. If there are a lot of iterations in order to find an object, its > index, or to remove it (or something else), perhaps it's worth supplying > these methods. After all, forEach(Consumer<T>) exists and it iterates while > calling accept(t) - not that different from iterating with test(t). > > P.S. lastIndexOf I find odd in the sense that it's the only method I found > that iterates backwards, We don't have, removeLast, removeIfBackwards, > forEachBackwards, a backwards for-each loop, or addLast (the latter is > add(list.size()-1, e); ). > > - Nir > > On Thu, Sep 17, 2020 at 1:32 AM Stuart Marks <stuart.ma...@oracle.com> > wrote: > >> >> >> On 9/16/20 1:59 PM, Remi Forax wrote: >> > ----- Mail original ----- >> >> De: "Nir Lisker" <nlis...@gmail.com> >> >> À: "core-libs-dev" <core-libs-dev@openjdk.java.net> >> >> Envoyé: Lundi 14 Septembre 2020 20:56:27 >> >> Objet: 'Find' method for Iterable >> > >> >> Hi, >> >> >> >> This has probably been brought up at some point. When we need to find >> an >> >> item in a collection based on its properties, we can either do it in a >> >> loop, testing each item, or in a stream with filter and findFirst/Any. >> >> >> >> I would think that a method in Iterable<T> be useful, along the lines >> of: >> >> >> >> public <T> Optional<T> find(Predicate<T> condition) { >> >> Objects.requireNonNull(condition); >> >> for (T t : this) { >> >> if (condition.test(t)) { >> >> return Optional.of(t); >> >> } >> >> } >> >> return Optional.empty(); >> >> } >> >> >> >> With usage: >> >> >> >> list.find(person -> person.id == 123456); >> >> >> >> There are a few issues with the method here such as t being null in >> >> null-friendly collections and the lack of bound generic types, but this >> >> example is just used to explain the intention. >> >> >> >> It will be an alternative to >> >> >> >> list.stream().filter(person -> person.id == 123456).findAny/First() >> >> (depending on if the collection is ordered or not) >> >> >> >> which doesn't create a stream, similar to Iterable#forEach vs >> >> Stream#forEach. >> >> >> >> Maybe with pattern matching this would become more appetizing. >> > >> > During the development of Java 8, we first tried to use >> Iterator/Iterable instead of using a novel interface Stream. >> > But a Stream cleanly separate the lazy side effect free API from the >> mutable one (Collection) and can be optimized better by the VM (it's a push >> API instead of being a pull API). >> > >> > The other question is why there is no method find() on Collection, i >> believe it's because while find() is ok for any DB API, find() is dangerous >> on a Collection because the execution time is linear, so people may use it >> instead of using a Map. >> >> >> Hi Nir, >> >> Rémi is correct to point out this distinction between the lazy operations >> (which >> appear on Stream) and the eager (and possibly mutating) operations on >> Collections. I >> think we want to preserve this distinction. >> >> While it might not be difficult to add a find() method to Iterable, why >> limit it to >> the find operation, and what about all the other operations available on >> Stream? >> Maybe what's necessary is a way to convert an Iterable to a Stream. In >> fact, this is >> already possible: >> >> StreamSupport.stream(iterable.spliterator(), false) >> >> Well, this is mouthful, so maybe there ought to be an easier way to >> convert an >> Iterable to a Stream. >> >> On the other hand, your examples use a list. The List interface already >> has methods >> indexOf/lastIndexOf which search the list for a particular object that's >> compared >> using equals(). It seems reasonable to consider similar methods that take >> a >> predicate instead of an object. >> >> Does either of these sound promising? >> >> s'marks >> >