У меня есть предикат, который принимает Optional<LocalDateTime>
, и я хочу проверить, присутствует ли он, а LocalDateTime
раньше текущей даты.
Я могу написать это с помощью операторов if, которые будут выглядеть так:
@Override
public boolean test(Optional<ResetPassword> resetPassword) {
if (resetPassword.isPresent()) {
if (!resetPassword.get().getValidUntil().isBefore(LocalDateTime.now())) {
throw new CustomException("Incorrect date");
}
return true;
}
return false;
}
Как я мог переписать это, используя функции Optional.map
и Optional.filter
?
@KarelG Optional
также имеет методы map
и filter
.
правда, но я считаю его устаревшим. Бесполезный.
Интересное мнение.
Вы не должны использовать Optional
как параметр для чего-либо. Он предназначен для использования только как возвращаемый тип.
Что ж, вы можете сделать это после потока сбора, чтобы иметь ту же семантику в конце цепочки (например, после .findAny()
) для преобразования объекта в другой тип, если это необходимо. Но за пределами этого? Также странно, что OP передает Optional
в качестве параметра. Я использую его только как возврат.
@marstran «Никогда не используйте необязательный параметр в качестве параметра чего-либо». В качестве безоговорочного напористого утверждения это просто неверно. Это вопрос стиля. Наличие необязательного типа параметра дает читателям понять, что параметр может иметь значение NULL, что упрощает работу с кодом.
@LiolikasBolikas: Кажется, нет хорошего способа решить вашу проблему с map
и filter
. Я думаю, ваше решение настолько хорошее, насколько это возможно. Я думаю, что причина трудностей в том, что желаемая комбинация результатов плохо согласуется с логикой Optional
. В вашем случае вы хотите работать с boolean
, ResetPassword
и исключениями, а это не совсем подходит для модели. Думаю...
@Lii Это определенно не безоговорочное заявление. Это утверждение исходит от самого Брайана Гетца. См. stackoverflow.com/a/26328555/4137489.
Я также выступал против использования Optional
в качестве параметра метода. Однако, если он предназначен для использования в качестве Predicate
, его использование в этом случае может быть оправданным. Это позволит вам взять поток Optional<ResetPassword>
и отфильтровать его с помощью этого предиката. Хотя семантически этот конкретный случай кажется немного странным, могут быть и другие случаи, когда он будет полезен. Еще более тревожным является тот факт, что этот метод в некоторых случаях вызывает исключение, что делает его совершенно непригодным для большинства применений в качестве Predicate
.
Цель этого предиката состояла в том, чтобы проверить объект ResetPassword, если он присутствует и если его время даты раньше текущего времени даты, а если нет, я просто выбрасываю исключение, которое обрабатывается глобальным обработчиком исключений, причина, по которой я добавил его в Predicate, заключается в том, чтобы просто связать несколько предикатов, перебирайте их и проверяйте правила, чтобы не было нескольких операторов if. Что вы посоветуете мне изменить в этом случае?
Вы никогда не должны использовать Optional
в качестве параметра чего-либо. Вместо этого вы должны позволить вашей функции принимать ResetPassword
и вызывать ее только в том случае, если присутствует значение Optional
.
Нравится:
public void test(ResetPassword resetPassword) {
if (!resetPassword.getValidUntil().isBefore(LocalDateTime.now())) {
throw new CustomException("Incorrect date");
}
}
А затем назовите это так:
resetPasswordOptional
.ifPresent(rp -> test(rp));
@Lii Это определенно не безоговорочное заявление. Это утверждение исходит от самого Брайана Гетца. См. stackoverflow.com/a/26328555/4137489.
Я надеюсь, что это поможет вам, кроме того, обратите внимание на исключение, которое вы выбрасываете, если это RuntimeException
, ваше приложение выйдет из строя в случае ложного условия.
public boolean test(Optional<ResetPassword> resetPassword) {
return resetPassword.isPresent() && resetPassword
.map(ResetPassword::getValidUntil)
.filter(localDateTime -> localDateTime.isBefore(LocalDateTime.now()))
.orElseThrow(() -> new CustomException("Incorrect date")) != null;
}
Это должно сработать! Я думаю, что то, что уже есть на плакате, яснее, но оно короче и, по крайней мере, использует map
и filter
! (Если это ваша цель ...)
.map
и.filter
предназначены для потоков, которые обычно поступают из коллекции. Нет смысла использовать их в объекте, не являющемся коллекцией.