> > 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).
No doubt, but a stream also creates overhead and is more cumbersome to use in the example I gave. Of course, I can create a helper static method `find(Collection<T>, Predicate<T>)`, but it's not much cleaner. (And the implementation can still be through Stream or Iterable,). I can ask about Iterable#forEach - is it there only because it was there to begin with? Would it have been a bad idea to add one if we had streams already? 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. I don't see a reason to put it Collection when it extends Iterable anyway, and the method just requires iteration. As for execution time, true, it's faster, but Map uses a lot more memory, so it's a tradeoff. For smaller lists, linear time is acceptable. Currently I'm using Maps actually, but I find that when there are many small maps, having many small lists is better for memory and the search time is similar. Additionally, a Map works only for searching by 1 key, but with a Collection/Iterable I can search by any property, and we're not about to use a Map for every property. So, overall, I don't think Map is a competitor in this market. It's also possible to specify that the complexity is linear in an @implNote to avoid surprises. - Nir On Wed, Sep 16, 2020 at 11:59 PM Remi Forax <fo...@univ-mlv.fr> 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. > > > > > - Nir > > Rémi >