Перепишите оператор if, используя необязательную карту и фильтр

У меня есть предикат, который принимает 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?

.map и .filter предназначены для потоков, которые обычно поступают из коллекции. Нет смысла использовать их в объекте, не являющемся коллекцией.
KarelG 31.10.2018 09:45

@KarelG Optional также имеет методы map и filter.

OhleC 31.10.2018 09:45

правда, но я считаю его устаревшим. Бесполезный.

KarelG 31.10.2018 09:45

Интересное мнение.

OhleC 31.10.2018 09:46

Вы не должны использовать Optional как параметр для чего-либо. Он предназначен для использования только как возвращаемый тип.

marstran 31.10.2018 09:50

Что ж, вы можете сделать это после потока сбора, чтобы иметь ту же семантику в конце цепочки (например, после .findAny()) для преобразования объекта в другой тип, если это необходимо. Но за пределами этого? Также странно, что OP передает Optional в качестве параметра. Я использую его только как возврат.

KarelG 31.10.2018 09:51

@marstran «Никогда не используйте необязательный параметр в качестве параметра чего-либо». В качестве безоговорочного напористого утверждения это просто неверно. Это вопрос стиля. Наличие необязательного типа параметра дает читателям понять, что параметр может иметь значение NULL, что упрощает работу с кодом.

Lii 31.10.2018 10:18

@LiolikasBolikas: Кажется, нет хорошего способа решить вашу проблему с map и filter. Я думаю, ваше решение настолько хорошее, насколько это возможно. Я думаю, что причина трудностей в том, что желаемая комбинация результатов плохо согласуется с логикой Optional. В вашем случае вы хотите работать с boolean, ResetPassword и исключениями, а это не совсем подходит для модели. Думаю...

Lii 31.10.2018 10:28

@Lii Это определенно не безоговорочное заявление. Это утверждение исходит от самого Брайана Гетца. См. stackoverflow.com/a/26328555/4137489.

marstran 31.10.2018 11:19

Я также выступал против использования Optional в качестве параметра метода. Однако, если он предназначен для использования в качестве Predicate, его использование в этом случае может быть оправданным. Это позволит вам взять поток Optional<ResetPassword> и отфильтровать его с помощью этого предиката. Хотя семантически этот конкретный случай кажется немного странным, могут быть и другие случаи, когда он будет полезен. Еще более тревожным является тот факт, что этот метод в некоторых случаях вызывает исключение, что делает его совершенно непригодным для большинства применений в качестве Predicate.

Stuart Marks 31.10.2018 17:10

Цель этого предиката состояла в том, чтобы проверить объект ResetPassword, если он присутствует и если его время даты раньше текущего времени даты, а если нет, я просто выбрасываю исключение, которое обрабатывается глобальным обработчиком исключений, причина, по которой я добавил его в Predicate, заключается в том, чтобы просто связать несколько предикатов, перебирайте их и проверяйте правила, чтобы не было нескольких операторов if. Что вы посоветуете мне изменить в этом случае?

LiolikasBolikas 02.11.2018 15:40
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
11
99
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы никогда не должны использовать Optional в качестве параметра чего-либо. Вместо этого вы должны позволить вашей функции принимать ResetPassword и вызывать ее только в том случае, если присутствует значение Optional. Нравится:

public void test(ResetPassword resetPassword) {
    if (!resetPassword.getValidUntil().isBefore(LocalDateTime.now())) {
        throw new CustomException("Incorrect date");
    }
}

А затем назовите это так:

resetPasswordOptional
    .ifPresent(rp -> test(rp));
«Никогда не используйте необязательный параметр в качестве параметра чего-либо». В качестве безоговорочного напористого утверждения это просто неверно. Это вопрос стиля. Наличие необязательного параметра в качестве типа дает читателям понять, что он может иметь значение NULL.
Lii 31.10.2018 10:09

@Lii Это определенно не безоговорочное заявление. Это утверждение исходит от самого Брайана Гетца. См. stackoverflow.com/a/26328555/4137489.

marstran 31.10.2018 11:17

Я надеюсь, что это поможет вам, кроме того, обратите внимание на исключение, которое вы выбрасываете, если это 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! (Если это ваша цель ...)

Lii 31.10.2018 10:49

Другие вопросы по теме