使用lambda过滤流并抛出异常

Nam*_*man 2 java lambda exception java-stream

目前我们使用的基本方法的实现Set<String> clients如下 -

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

for (String client : clients) {
    if (!myMay.containsKey(client)) {
        throw new InvalidClientException(client);
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用lambda表达式转换它,如下所示 -

clients.stream().filter(client -> !myMay.containsKey(client) || clients.isEmpty())
            .forEach(InvalidClientException::new);
Run Code Online (Sandbox Code Playgroud)

但这似乎不是以同样的方式工作,参数化构造函数在这里调用错过了吗?

JB *_*zet 5

首先,如果set为空,则传递给forEach的lambda将不会被执行:空流为空,过滤它不会向其添加任何元素.只有可能删除一些.

其次,lambda创建了一个例外.但它并没有抛弃它.

您可以使用

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

编辑:我错过了你想将不在集合中的(第一个?)客户端传递给异常的事实.要做到这一点,你可以做到

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

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

但是,只有在异常是运行时异常时才会起作用,因为您不能从Consumer中抛出已检查的异常.如果它是一个已检查的异常,并且您确实希望将其保留为已检查的异常,则可以使用

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());
}
Run Code Online (Sandbox Code Playgroud)