0

I have some code that throws a checked exception. I want to call that code within a lambda in order to create a map from another map:

Map<String, Coordinate> map = getMap();
Map<String, Integer> result = map.entrySet().stream().collect(
    toMap(x -> x.getKey(), x -> doSomething(x.getValue)));

where doSometing is the code that throws the exception:

int doSomething(Coordinate c) throws MyException { ... }

Now compiler surely complains about the exception not being handled. So I surround it with a try-catch, which looks pretty ugly:

Map<String, Integer> result = map.entrySet().stream().collect(
    toMap(x -> x.getKey(), x -> {
        try {
            return doSomething(x.getValue());
        } catch (MyException e) {
            e.printStackTrace();
            // return some error-code here???
        }
    }));

which also does not compile as we need to return something in the catch-case. However there´s not much sense in returning anything here in this exceptional case, which is why I actually do not want to handle the exception at that level. Can´t I just handle the exception in my calling code, where I create the lambda? So to say just one level above?

try {
    Map<String, Integer> result = ...
} catch (MyException e) { ... }

But that does not compile because the exception thrown from the lambda is not handled.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • 1
    The question here would be, why would you want to use checked exception. Also, I believe that the standard way of handling checked exceptions in labdas (if you cannot just make it runtime) is to catch it inside lamda and rethrow an unchecked exception - you can use checked one as cause. – Worthless Feb 04 '20 at 14:08
  • @Worthless Unfortunately `doSomething` is a 3rd-party-API that just throws. – MakePeaceGreatAgain Feb 04 '20 at 14:09
  • Then yea, rethrowing is probably the easiest way to handle it. – Worthless Feb 04 '20 at 14:10
  • @Worthless But how to do that in a nice way? Isn´t it possible to just let the exception bubble through the layers until it finally **is** handled? – MakePeaceGreatAgain Feb 04 '20 at 14:12
  • Checked exceptions can't bubble through until it is handled. Each intervening method has to declare it. – matt freake Feb 04 '20 at 14:16
  • Does this answer your question? [Java 8 Lambda function that throws exception?](https://stackoverflow.com/questions/18198176/java-8-lambda-function-that-throws-exception) – mrod Feb 04 '20 at 14:19

2 Answers2

1

From Baeldung's blog: you could define consumer which can throw Exception:

@FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
    void accept(T t) throws E;
}

and a static wrapper to map checked exception to RuntimeException:

static <T> Consumer<T> throwingConsumerWrapper(
  ThrowingConsumer<T, Exception> throwingConsumer) {

    return i -> {
        try {
            throwingConsumer.accept(i);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    };
}

Then you can call it:

Map<String, Integer> result = map.entrySet().stream()
    .collect(
        throwingConsumerWrapper(toMap(x -> x.getKey(), x -> doSomething(x.getValue)))
    );
diginoise
  • 7,352
  • 2
  • 31
  • 39
0

Fist of all it's worth to filter your values. In case if you have values which can raise an exception.

Then you can use one of the popular wrappers (i.e. jooq.lambda) or write your own

 map.entrySet().stream()
    .filter(x -> makeSureNoExtection(x))
    .collect(toMap(x -> x.getKey(), unchecked(x -> doSomething(x.getValue))));
dehasi
  • 2,644
  • 1
  • 19
  • 31