Q on Patterns and Streams

Brian Goetz brian.goetz at oracle.com
Wed Jan 20 14:54:24 UTC 2021


Indeed, this is a question we've wrestled with.

You are right that this is a sort of flatMap.  And that the current 
flatMap doesn't express it very nicely, or efficiently.

We've recently added another form of flatMap, mapMulti, which is a lot 
more efficient; in that version, your example would be:

     .mapMulti((e,s) -> { if (e instanceof P(b)) s.accept(b); })

If `void` were a type, we could express this as an expression lambda:

     .mapMulti((e,s) -> e instanceof P(b) ? s.accept(b) : void )

A variant of mapMulti optimized for zero-or-one (which would be more 
sensible when Optional is a primitive class) might be:

     .mapMaybe(e -> Optional.ofNullable(e instanceof P(b) ? b : null) )

where mapMaybe takes a T -> Optional<U>.

Note that the use of patterns here is limited to the case where you are 
going to package up all the bindings into a single value.

There's some other possibilities but I want to think about them some 
more before discussing them.


On 1/19/2021 7:30 PM, Johannes Kuhn wrote:
> Turns out I sometimes write code that looks like this:
>
>     foos.stream().filter(e -> e instanceof Foo).map(e -> (Foo) e)...
>
> or
>
> foos.stream().filter(Foo.class::isInstance).map(Foo.class::cast)...
>
> Nicolas Fränkel has even written a blog post about this[1].
>
> Anyway, this can be expressed with a single stream operation:
>
>     foos.stream().flatMap(e -> e instanceof Foo foo ? Stream.of(foo) : 
> Stream.of())...
>
> I expect that form to work with any pattern in the future.
> But it doesn't look great.
>
> Are there any plans around this?
> Or is this something patterns shouldn't be used for?
>
> In a more general way - will there be a way to pass a pattern as an 
> argument to some other function?
>
> - Johannes
>
>
>
> [1]: https://blog.frankel.ch/changing-coding-habits-stream-friendly/



More information about the amber-dev mailing list