Возврат из Java Необязательный ifPresent () - PullRequest
0 голосов
/ 26 февраля 2019

Я понимаю, что вы не можете вернуться с ifPresent(), поэтому этот пример не работает:

public boolean checkSomethingIfPresent() {
    mightReturnAString().ifPresent((item) -> {
        if (item.equals("something")) {
            // Do some other stuff like use "something" in API calls
            return true; // Does not compile
        }
    });
    return false;
}

Где mightReturnAString() может вернуть действительную строку или пустую необязательную,Что я сделал, это работает:

public boolean checkSomethingIsPresent() {
    Optional<String> result = mightReturnAString();

    if (result.isPresent()) {
        String item = result.get();
        if (item.equals("something") {
            // Do some other stuff like use "something" in API calls
            return true;
        }
    }
    return false;
}

, который длиннее и не сильно отличается от простой проверки на нулевые значения в первую очередь.Я чувствую, что должен быть более краткий способ использования Optional.

Ответы [ 4 ]

0 голосов
/ 26 февраля 2019

Идеальным решением является разделение «команда-запрос»: создайте один метод (команду) для выполнения чего-либо со строкой, если она присутствует.И еще один метод (запрос), чтобы сказать вам, был ли он там.

Однако мы не живем идеальным миром, и идеальные решения никогда не возможны.Если в вашей ситуации вы не можете разделить команду и запрос, мне по вкусу идея, уже представленная shmosel: map для boolean.В качестве детали я бы использовал filter, а не внутренний оператор if:

public boolean checkSomethingIfPresent() {
    return mightReturnAString().filter(item -> item.equals("something"))
            .map(item -> {
                // Do some other stuff like use "something" in API calls
                return true; // (compiles)
            })
            .orElse(false);
}

Что мне не нравится в этом, так это то, что цепочка вызовов имеет побочный эффект, который обычно не ожидаетсякроме ifPresent и ifPresentOrElse (и, конечно, orElseThrow).

Если мы настаиваем на использовании ifPresent, чтобы сделать побочный эффект более четким, это возможно:

    AtomicBoolean result = new AtomicBoolean(false);
    mightReturnAString().filter(item -> item.equals("something"))
            .ifPresent(item -> {
                // Do some other stuff like use "something" in API calls
                result.set(true);
            });
    return result.get();

Я использую AtomicBoolean в качестве контейнера для результата, поскольку нам не разрешено присваивать примитиву boolean изнутри лямбды.Нам не нужна его атомарность, но она также не вредит.

Ссылка: Разделение команд и запросов в Википедии

0 голосов
/ 26 февраля 2019

Я думаю, что все, что вы ищете, это просто filter и проверьте наличие:

return result.filter(a -> a.equals("something")).isPresent();
0 голосов
/ 26 февраля 2019

Хотя @nullpointer и @Ravindra показали, как объединить Optional с другим условием, вам придется сделать немного больше, чтобы иметь возможность вызывать API и делать другие вещи, как вы задали в вопросе.Следующее выглядит довольно читабельным и лаконичным на мой взгляд:

private static boolean checkSomethingIfPresent() {
    Optional<String> str = mightReturnAString();
    if (str.filter(s -> s.equals("something")).isPresent()) {
        //call APIs here using str.get()
        return true;
    }
    return false;
}

Лучшим дизайном было бы использование цепочек методов:

private static void checkSomethingIfPresent() {
    mightReturnFilteredString().ifPresent(s -> {
        //call APIs here
    });
}

private static Optional<String> mightReturnFilteredString() {
    return mightReturnAString().filter(s -> s.equals("something"));
}

private static Optional<String> mightReturnAString() {
    return Optional.of("something");
}
0 голосов
/ 26 февраля 2019

Как насчет отображения на логическое значение?

public boolean checkSomethingIfPresent() {
    return mightReturnAString().map(item -> {
        if (item.equals("something")) {
            // Do some other stuff like use "something" in API calls
            return true; // Does not compile
        }
        return false; // or null
    }).orElse(false);
}
...