nullpointer nullpointer - 3 months ago 13
Java Question

Using lambda to filter stream and throw an exception

Currently our implementation of a base method using

Set<String> clients
was as follows -

if (clients.isEmpty()) {
throw new InvalidClientException();
}

for (String client : clients) {
if (!myMay.containsKey(client)) {
throw new InvalidClientException(client);
}
}


I tried converting it using lambda expression as follows -

clients.stream().filter(client -> !myMay.containsKey(client) || clients.isEmpty())
.forEach(InvalidClientException::new);


But this seems to be not working the same way, is the parameterised constructor call a miss here?

Answer

First of all, if the set is empty, the lambda passed to forEach won't be executed: an empty stream is empty, and filtering it won't add any element to it. Only potentially remove some.

Second, the lambda creates an exception. But it doesn't throw it.

You can use

if (clients.isEmpty() || clients.stream().anyMatch(client -> !myMay.containsKey(client))) {
    throw new InvalidClientException();
}

EDIT: I missed the fact that you wanted to pass the (first?) client not in the set to the exception. To do that, you can do

if (clients.isEmpty()) {
    throw new InvalidClientException();
}

clients.stream()
       .filter(client -> !myMay.containsKey(client))
       .findAny() // or .findFirst()
       .ifPresent(client -> {
           throw new InvalidClientException(client);
       });

That will only work if the exception is a runtime exception, though, because you can't throw a checked exception from a Consumer. If it's a checked exception and you really want to keep it a checked exception, you can use

if (clients.isEmpty()) {
    throw new InvalidClientException();
}

Optional<String> wrongClient = 
    clients.stream()
           .filter(client -> !myMay.containsKey(client))
           .findAny();
if (wrongClient.isPresent()) {
    throw new InvalidClientException(wrongClient.get());
}
Comments