Объединяя два варианта, самый чистый способ написать? - PullRequest
2 голосов
/ 14 марта 2020

Предположим, у меня есть:

public void func(){
  Optional<Integer> firstRequiredOptional = ...
  Optional<Integer> secondRequiredOptional = ...

  if(firstRequiredOptional.isPresent() && secondRequiredOptional.isPresent()){
     // do something with values of BOTH optionals
  }

  // Do nothing
}

Эта функция будет выполнять if только при наличии ОБА дополнительных опций.

Я пытаюсь придумать более чистый способ (возможно, функцию ifPresent тип) способ написания этого или преобразования каким-либо образом в Optional<Integer, Integer> с обоими типами в одном необязательном порядке, если это возможно?

Какой более чистый способ написать это?

Ответы [ 4 ]

4 голосов
/ 14 марта 2020

Использование оператора if уже чище, чем другие альтернативы.

альтернатива 1

Вы можете использовать ifPresent, например:

firstRequiredOptional.ifPresent(first ->
        secondRequiredOptional.ifPresent(second -> something(first, second)));

альтернатива 2

Используйте allMatch с Stream на тот случай, если вы не хотите использовать значения (хотя это невозможно), например:

if (Stream.of(firstRequiredOptional, secondRequiredOptional)
        .allMatch(Optional::isPresent)) {
    something(); // or something(firstRequiredOptional.get(), secondRequiredOptional.get()); 
}
0 голосов
/ 14 марта 2020

Не уверен, что чище, но мое интуитивно понятное решение - предоставить контейнер и использовать ofNullable.

Это может быть что-то вроде:

public class DualOptional<T, K>
    {
        Optional<T> opt1 = Optional.empty();
        Optional<K> opt2 = Optional.empty();

        DualOptional( T t, K k )
        {
            opt1 = Optional.ofNullable( t );
            opt2 = Optional.ofNullable( k );
        }

        public boolean isPresent()
        {
            return opt1.isPresent() && opt2.isPresent();
        }
    }

Это, конечно, может быть расширен за счет получения геттеров и любых других необходимых функций.

0 голосов
/ 14 марта 2020

Возможно универсальный c подход для двух опциональных:

import java.util.Optional;
import java.util.function.BiConsumer;

public class OptionalUtils {

    public static <T> void ifPresent(Optional<T> optional1, Optional<T> optional2, BiConsumer<T, T> consumer) {
        if (optional1.isPresent() && optional2.isPresent()) {
            consumer.accept(optional1.get(), optional2.get());
        }
    }

    public static void main(String[] args) {

        Optional<Integer> test1 = Optional.of(1);
        Optional<Integer> test2 = Optional.of(2);

        ifPresent(test1, test2, (a, b) -> {
            System.out.println(" a + b =" + (a + b));
        });

    }
}
0 голосов
/ 14 марта 2020

Зависит от того, что вы подразумеваете под «чище».

Решение ifPresent, как указывает @Naman, выглядит следующим образом:

firstRequiredOptional.ifPresent(firstValue ->
    secondRequiredOptional.ifPresent(secondValue -> {
        // do something with firstValue, secondValue.
    }));

Это «чище» в ощущение, что вам не нужно вызывать оба значения .isPresent() и .get() для двух дополнительных опций.

Нет Optional<FirstType, SecondType>, но если комбинация этих двух обязательных значений имеет какое-то значение, вы Возможно, вы захотите воплотить это в классе.

Optional<FullName> fullNameOptional = firstNameOptional.flatMap(firstName ->
    secondNameOptional.map(secondName -> new FullName(firstName, secondName));
fullNameOptional.ifPresent(fullName -> {
    // do something with fullName.
});

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

Если вам нравится идея преобразования в один Optional, но вы не хотите создавать тип просто для этого вы можете создавать универсальные классы Tuple (или использовать одну из нескольких популярных библиотек Tuple).

...