Filtering with flatMap

Leave a comment
Dev

Checked exceptions are annoying. They are especially annoying when they may be thrown inside a lambda where they can really interrupt the flow.

What if you wanted to map a function over a list to collect values but a checked exception might get thrown in the process? In that case you don’t want the whole stream to stop executing but perhaps just log it and carry on with the next element.

Here’s how you might have done it with Java 7; if an exception is thrown we just log it and don’t add it to the output list.

public List<String> theOldWay(List<String> input) {
    List<String> output = new ArrayList();
    for (String s : input) {
        try {
            String value = methodThatMayThrowException(s);
            output.add(value);
        } catch (Exception e) {
            log.info("Caught an exception", e);
        }
    }
    return output;
}

With Java 8 we can use a combination of flatMap and empty streams to effectively filter out all the items that threw an exception.

public List<String> oneWeirdTrick(List<String> input) {
    return input.stream()
            .flatMap(s -> {
                try {
                    String value = methodThatMayThrowException(s);
                    return Stream.of(value);
                } catch (Exception e) {
                    log.info("Caught an exception", e);
                    return Stream.empty();
                }
            })
            .collect(Collectors.toList());
}

Those elements that were successful will be wrapped in a stream and those that threw an exception will return an empty stream. The call to flatMap  will throw away all the empty streams and leave you with a stream of “unwrapped” values to be collected.

Leave a Reply

Your email address will not be published. Required fields are marked *