I think that the discussion is still at the level of if it's an acceptable addition and not yet at where to implement it. I gave my reasoning in response to Stuart's points as to what I think is acceptable and what isn't. Whether the java.lang package has special status is a bit ahead of where we are now.
On Wed, Nov 11, 2020 at 7:22 PM Justin Dekeyser <justin.dekey...@gmail.com> wrote: > Hello all, > > Were those downsides seriously considered and strongly argued against? : > > (1) Iterable belongs to java.lang so, at least from how it is usually > approached, it's a feature at the very level of the language, not a > util feature like Collection. Adding a find on it, is it really > relevant, or should it be concerned with the simple idea of unlocking > the enhanced-for loop syntax? > > (2) For the find() method to stop on any Iterable, the Iterable should > have finite size. This mean the size() method can be implemented too, > by this move: > ```java > default int size() { > int[] dummy = { 0 }; > Predicate<T> falsy = $ -> { dummy[0] += 1; return false; } > find(falsy); > return dummy[0]; > } > ``` > At the very moment an Iterable<T> also has a size(), a Collection<T> > implementation can be provided (since the altering methods add/remove > are optional in this spec). So , long story short: > > Adding a find() method on Iterable<T> with a contract that it stops > (stops, and not just linear search time), makes it a Collection. It > really looks like a nonsense. Or maybe you're going to relax the "this > method is guaranteed to stop" from the spec? Is it then still > relevant? > > Note: This (2) problem is not a problem for now, because all the utils > that turns Iterable<T> to a collection like stuff, or a Stream, are > actually features *on those latter* classes. Hence it's not a concern > of Iterable<T> itself. > The problem with (1) is really a communication problem: nothing is > made in the Java documentation to clearly indicate whether or not > Iterable should be used businesswise, or is it only for > syntax-enhancement. (The same problem goes for AutoCloseable: you'll > really find two schools out of there.) > > (3) To my opinion, most people are using Iterable either from a > collection (where the .stream().filter(p).findAny() makes the job. > It's not perfect but it's quite clear and flexible) or with a > ResultSet, where the SQL procedure could/should be used anyway. The > other cases look so exotic (but I might be wrong) that I really wonder > how a find method on a Iterable (and not Collection) stuff can be felt > so useful and language fundamental, that it should be in the java.lang > package. > > Best regards, > > Justin Dekeyser > > On Tue, Nov 10, 2020 at 7:02 PM Nir Lisker <nlis...@gmail.com> wrote: > > > > 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 > > >> > > > >