'Find' method for Iterable
Nir Lisker
nlisker at gmail.com
Wed Sep 16 21:36:58 UTC 2020
>
> 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 <forax at univ-mlv.fr> wrote:
> ----- Mail original -----
> > De: "Nir Lisker" <nlisker at gmail.com>
> > À: "core-libs-dev" <core-libs-dev at 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
>
More information about the core-libs-dev
mailing list