RFR : JDK-8001642 : Add Optional<T>, OptionalDouble, OptionalInt, OptionalLong

Brian Goetz brian.goetz at oracle.com
Fri Mar 15 12:06:36 PDT 2013


Even ignoring infinite streams, it would still perform poorly on large 
streams if generating the stream elements (or the upstream operations) 
have any cost whatsoever.

The short-circuiting ops (find, matchXxx, and limit) force traversal to 
use tryAdvance instead of forEach, to be more responsive.

There really are two orthogonal considerations with find:

  - Should find() take a predicate, or not?
  - How do we specify what to return if you find nothing?

It seems to me that people gravitate towards the predicate version 
because of the name "find", but if it were just called "first", they 
might feel differently.  In any case, I find the predicate version a 
distraction:
  - You can always specify a predicate using an upstream filter(), which 
is not that much less efficient, just one more pipeline stage. 
Specifying the predicate in find is just a fusing optimization, and not 
one that saves a lot of extra work.
  - For people who just want the first, having to specify a "no-op" 
predicate is annoying.  Which pushes us back to two versions, a 
predicate-version and a predicate-less version -- and I don't think the 
predicate version carries its weight.  However, maybe the name is just 
wrong.

The second is the Optional vs default.  We're not revisiting the 
"whither Optional" discussion here; what we're discussing here is 
whether it is better to have both, for both findXxx and various reduce.

   Optional<T> findFirst()
   T findFirstOrElse(T sentinal)

The argument in favor of both is that the latter is more efficient, 
without running into the "null might mean nothing or might mean that the 
first element was null" problem.  Though I suspect a lot of people would 
use null as the sentinel and then shoot themselves in the foot anyway.




On 3/15/2013 2:56 PM, Joe Bowbeer wrote:
> It wasn't obvious to me until recently that it is the short-circuiting
> behavior of the 'find' methods that is hardest to derive.
>
> Without short-circuiting, findFirst forms could be derived as follows,
> but they will fail on infinite streams:
>
> T findFirst(T ifNone) {
>    return reduce(ifNone, (l, r) -> (l != ifNone) ? l : r);
> }
>
> T findFirst(Predicate<? super T> predicate, T ifNone) {
>    return reduce(ifNone, (l, r) -> (l != ifNone || !predicate.test(r)) ?
> l : r);
> }
>
> I'm not sure why, but I'm liking the idea of only adding
> findAny(predicate, ifNone).
>
> --Joe
>
>
> On Fri, Mar 15, 2013 at 8:04 AM, Doug Lea <dl at cs.oswego.edu
> <mailto:dl at cs.oswego.edu>> wrote:
>
>     On 03/15/13 09:46, Brian Goetz wrote:
>
>         Wouldn't the minimal change NOT have a predicate, to match the
>         existing form of
>         findFirst?
>
>             Optional<T> findFirst()
>             T findFirst(T orElse)
>
>
>     Yes and no. The only way to get non-optional-bearing
>     result for search would otherwise be s.filter(pred).findAny(),
>     which entails buffering of stuff you will throw away.
>
>     This is also the reason only adding why findAny(pred) (not findDirst)
>     is defensible: the alternative is of most interest to the sort of
>     person who want to avoid that Optional too.
>
>     -Doug
>
>
>
>
>
>         On 3/15/2013 7:31 AM, Doug Lea wrote:
>
>             On 03/15/13 06:26, Joe Bowbeer wrote:
>
>                 Doug,
>
>                 I think your point that Optional and non-Optional forms
>                 of reduce are
>                 already
>                 provided is significant.
>
>                 I noticed that your proposed versions of findFirst and
>                 findAny have a
>                 Predicate
>                 argument, but the Optional forms do not:
>
>                 T findFirst(Predicate<? super T> predicate, T ifNone);
>
>                 Why is this?
>
>
>
>             It's in the spirit of proposing a minimal change. The predicate
>             form suffices for all Optional-avoiding search stuff. To reduce
>             impact by another 50%, it would suffice to ONLY include the
>             "any" form.
>                 T findAny(Predicate<? super T> predicate, T ifNone);
>
>             -Doug
>
>
>
>
>
>
>
>


More information about the lambda-libs-spec-observers mailing list