Java Reference
In-Depth Information
public ResultMap(final Consumer<Exception> exceptionHandler) {
Objects.requireNonNull(exceptionHandler, "exception handler");
this.exceptionHandler = exceptionHandler;
}
/**
* Applies this function to the given argument.
* If the result container has a result, a stream containing only that result
* is returned.
* If the result container has an exception, the exception handler is called
* and the empty stream is returned.
* If the argument is {@code null}, the empty stream is returned.
*
* @param resultContainer The container for results; may be {@code null}.
* @return a 0 or 1 element stream with the result, if any.
*/
@Override
public Stream<RESULT_T> apply(final Result<RESULT_T> resultContainer) {
// Handle any obnoxious boundaries with short-circuiting
if (resultContainer == null) return Stream.empty();
// First argument is what to do with exceptions,
// Second argument is what to do with results
return resultContainer.map(
error -> {
exceptionHandler.accept(error);
return Stream.empty();
},
Stream::of
);
}
}
It's truly beautiful how simple functional programming makes this kind of processing. For an added
benefit, consider how simple it would be to unit test this kind of class, exercising its API completely. (If you
would like to go see, look up this class in Webonise Lab's FunJava library.) With our class available, let's
create a place to use it by generating our stream.
Streaming all the Lines of all the Files in a Directory
With our support class in place, we can now turn toward the main piece of our functionality. We want to
process a
java.io.File
and return a
Stream
of
Result
instances, each containing either an
IOException
or
a
String
of the line of the file. The general breakdown of the implementation will be this:
File
dir
=> Stream<Result<String>>:
For each file in
dir
, execute...
File
file
=> Stream<Result<String>>:
Return all the lines in
file