Whoops, wrong mailing list -- should have been core-libs-dev instead.

I'll make a new thread there. Please ignore this one.

On Mon, Jun 1, 2026 at 8:09 PM David Alayachew <[email protected]>
wrote:

> Hello @[email protected] <[email protected]>,
>
> I am building a simple utility that searches a bunch of files for keywords.
> Let's assume that the act of opening a file for reading is very likely to
> produce an exception.
>
> Currently, my code looks something like this.
>
> record Result(Path file, String line) {}
>
> Stream<Result> search(final String keyword)
> {
>     return
>         Files
>             .walk(Path.of("."))
>             .filter(Files::isRegularFile)
>             .flatMap
>             (
>                 file ->
>                 {
>                     try
>                     {
>                         return
>                             Files
>                                 .lines(file)
>                                 .filter(line -> line.contains(keyword))
>                                 .map(line -> new Result(file, line))
>                                 ;
>
>                     }
>                     catch (final Exception exception)
>                     {
>                         throw new IllegalStateException("Failed for " +
> file, exception);
>                     }
>                 }
>             )
>             ;
> }
>
> Now, the bug here is obvious from a glance -- that try-catch in flatMap()
> doesn't really do what I want. Since Streams are lazy, none of the actual
> file opening logic will occur inside the try-catch.
>
> Ok, there are a couple of workarounds here. The most obvious one is just to
> execute a terminal operation, like calling Stream::toList followed by
> List::stream.
>
> Now this works, but it is not clear that that is the right solution here.
> For starters, have I unknowingly opted-out of performance enhancements that
> stream could have otherwise given me? I know Streams are lazy, but I don't
> know "how lazy" they are. Once the body of the flatMap() lambda is reached,
> does it fetch the whole stream contents right away? Does it grab only a few
> at a time from each resulting stream, round-robin style? Something else?
>
> I could look at the code to find out, but that only gives me the current
> behaviour. And since the documentation for flatMap() doesn't say anything
> about it, I am led to believe that the fetching behaviour is unspecified.
> It's only specified that it will grab them all, but it is not clear when
> and how "eagerly" it would.
>
> Anyways, all of that to say, rather than calling toList() or something
> else, wouldn't it be better if I could put the logic of try catch into the
> stream itself? Something like being able to wrap whatever exception is
> thrown from stream?
>
> This solves the problem of making sure I don't miss out on any features or
> performance enhancements provided by the stream library. I can just specify
> the behaviour I want -- to wrap the thrown exception in another exception.
> That feels very much in the spirit of the Stream API.
>
> Anyways, my idea looks like this.
>
> Files
>     .lines(file)
>     .filter(line -> line.contains(keyWord))
>     .wrapException(Exception.class, (Exception e) -> new
> WrapperException("Failed for " + file, e))
>     ;
>
> The signature of wrapException is as follows.
>
> public <EXC1, EXC2> Stream<T> wrapException(Class<EXC> excClass,
> Function<EXC1, EXC2> excTransformer)
>
> Now, I know the Stream API is very complex, but I really do think this
> carries its weight. We can greatly improve existing error messages while
> still keeping in the spirit of the Stream API -- provide the desired
> behaviour and let it figure out how to do it.
>
> Please let me know your thoughts.
>
> Thank you for your time and consideration.
> David Alayachew
>

Reply via email to