Muresan Vladut
Muresan Vladut

Reputation: 3

executor.invokeAll() lambda body does not return

The idea is for some kind of compiler, and I'm trying to implement a fork statement that starts another thread. The code:

List < Callable < CustomClass >> callList = lista.stream().map(p -> (Callable < CustomClass > )() -> p.oneStep()).collect(Collectors.toList()); //here I just prepared the list of callables
List < CustomClass > newPrgs;
try {
    newPrgs = executor.invokeAll(callList).stream().map(future -> {
        try {
            return future.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /here it indicates the error/.filter(p -> p != null).collect(Collectors.toList());
} catch (InterruptedException e) {
    throw new CustomException(e.getMessage());
}

The error is: lambda body is neither value nor void compatible. I tried all sort of changes and tricks, and no result. Some help please?

Upvotes: 0

Views: 748

Answers (2)

RealSkeptic
RealSkeptic

Reputation: 34628

Take a look at your lambda's body:

try {
    return future.get();   // This branch returns a value
} catch (Exception e) {
    e.printStackTrace(); // No return statement here
}
// No return statement here either

So your lambda can neither be translated into a void method, not into a method with a return value.

You should have a return value either at the catch or at the end of the lambda body.

Upvotes: 1

sisyphus
sisyphus

Reputation: 6392

The problem is in the definition of your lambda...

{
    try{
      return future.get();
    }
    catch (Exception e){
      e.printStackTrace();
    }
}

Now, this is fine for the happy path, which just returns the response from the future, but in the event of an exception this lambda will not return a value. You need to return something from the exception case, or throw a RuntimeException. Which to do depends on your use case - an exception will stop the entire stream from processing, but a null or default value could risk polluting your stream.

Also, it's generally best not to catch Exception - keep the catch down to the minimal set necessary / that you can handle.

The exception-throwing form would look like...

{
    try{
      return future.get();
    }
    catch (InterruptedException | ExecutionException e){
      e.printStackTrace();
      throw new RuntimeException(e)
    }
}

Upvotes: 1

Related Questions