Есть ли более элегантный способ фильтрации в случае возникновения исключения?
Я имею в виду, что в настоящее время мой код выглядит так:
stream.filter(item -> {
try {
validator.with(reference)
.hasAccess(this.authzManager)
.isOwner();
} catch (EspaiDocFault | DataAccessException e) {
return false;
}
return true;
}
)
То, что я пытаюсь сделать, - это если возникает исключение, текущий поток элементов должен быть отфильтрован.
Я ищу любой существующий класс утилиты или что-то подобное ...
@FedericoPeraltaSchaffner Нет, я не могу изменить эти методы
А как насчет того, что элемент потока (item) не используется внутри предиката filter?
@FedericoPeraltaSchaffner, и возвращаемое значение isOwner полностью игнорируется ....
@Aomine Да, но я думаю (с небольшим количеством воображения) это могло быть сделано намеренно, то есть если OP просто хотел отсутствие или наличие исключения в качестве побочного эффекта, чтобы проверить, все ли в порядке ... Кто знает? В любом случае, похоже, плохой дизайн ...
@FedericoPeraltaSchaffner Теперь, когда вы упомянули, это имеет больше смысла, но все же ответ на ваш предыдущий вопрос должен быть интересным.




В библиотеке Вавр есть класс Try, который может делать то, что вы хотите:
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()))
где,
ItemType - это тип item;Exception является общим родителем EspaiDocFault и DataAccessException..stream()
.filter(EPredicate.unwrap(item -> validator.[...].isOwner()))
Было бы более элегантно, если бы вы вызывали разные методы, которые возвращают false (или пустой Optional, который вы можете связать со следующим вызовом с
map) вместо того, чтобы генерировать эти исключения.