java 流:根据抛出的异常进行过滤的优雅方式

java streams: elegant way to filter according an exception is thrown

有没有更优雅的方法根据是否抛出异常进行过滤?

我的意思是,目前我的代码如下所示:

stream.filter(item -> {
    try {
        validator.with(reference)
            .hasAccess(this.authzManager)
            .isOwner();
        } catch (EspaiDocFault | DataAccessException e) {
            return false;
        }
        return true;
    }
)

我想做的是,如果抛出异常,则必须过滤当前项目流。

我正在寻找任何现有的实用程序 class 或类似的东西...

Vavr 库有一个 Try class 可以做你想做的事:

stream.filter(item -> Try.of(() -> validator.with(reference)
                .hasAccess(this.authzManager)
                .isOwner()).getOrElse(false))

编辑:如果你真的想知道是否抛出异常,Vavr 也可以做到:

stream.filter(item -> Try.of([...]).isSuccess())

或者,将整个事情包装在一个方法中:

stream.filter(this::getMyBooleanWithinMyTry)

我在许多变体中看到的一种非常常见的方法是编写自己的功能接口,允许抛出已检查的异常 (1) 并使该解决方案适应内置接口 (2)。

/**
 * An EPredicate is a Predicate that allows a checked exception to be thrown.
 *
 * @param <T> the type of the input to the predicate
 * @param <E> the allowed exception
 */
@FunctionalInterface
public interface EPredicate<T, E extends Exception> {

    /**
     * (1) the method permits a checked exception
     */
    boolean test(T t) throws E;

    /**
     * (2) the method adapts an EPredicate to a Predicate.
     */
    static <T, E extends Exception> Predicate<T> unwrap(EPredicate<T, E> predicate) {
        return t -> {
            try {
                return predicate.test(t);
            } catch (Exception e) {
                return false;
            }
        };
    }

}

一个例子看起来很优雅:

.stream()
.filter(EPredicate.<ItemType, Exception>unwrap(item -> validator.[...].isOwner()))

其中,

  • ItemTypeitem的类型;
  • ExceptionEspaiDocFaultDataAccessException 的共同父级。

.stream()
.filter(EPredicate.unwrap(item -> validator.[...].isOwner()))