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 >
