2016-09-23 6 views
4

Моя проблема: у меня есть два или более варианта, которые обертывают разные типы. Я хочу выполнить операцию, которая может быть выполнена только в том случае, если все опции не пусты.Объединить Java 8 Варианты с условным И

В настоящее время Im делает это таким образом:

Optional<PatientCase> caseOptional = patientCaseRepository.findOneById(caseId); 
    Optional<User> userOptional = userRepository.findOneById(caseId); 

    if(userOptional.isPresent() && caseOptional.isPresent()) { 
     caseOptional.get().getProcess().setDesigner(userOptional.get()); 
    } 

На мой взгляд, если условие не чувствует себя хорошо. Я знаю, что можно связать Опционы с помощью orElse. Но в моем случае я не хочу логического Else. Есть ли способ создать и оператор ИИ для объединения двух или более опций , похожих на этот код PSEUDO?

caseOptional.and.userOptional.ifPresent((theCase,user) -> //Perform Stuff); 

ответ

5

Существует логическая операция И, но не существует (простой) способ превратить его в два-значения Optional, другими словами, это (снова) страдает от отсутствия пар или кортежей типов. Например.

caseOptional.flatMap(theCase -> userOptional 
     .map(user -> new AbstractMap.SimpleEntry<>(theCase, user))) 
    .ifPresent(e -> e.getKey().getProcess().setDesigner(e.getValue())); 

который использует AbstractMap.SimpleEntry в режиме ожидания в течение отсутствующего типа кортежа.

В качестве альтернативы можно использовать одноэлементную карту в качестве пары:

caseOptional.flatMap(theCase -> userOptional 
     .map(user -> Collections.singletonMap(theCase, user))) 
    .ifPresent(m -> m.forEach((c, u) -> c.getProcess().setDesigner(u))); 

Но в данном конкретном случае, вы можете использовать более простого

caseOptional.map(PatientCase::getProcess) 
      .ifPresent(p -> userOptional.ifPresent(p::setDesigner)); 

или

caseOptional.ifPresent(c -> userOptional.ifPresent(u -> c.getProcess().setDesigner(u))); 

вместо ,

+0

Последней форма выглядит очень похожа на монады, может быть, она может быть оформлена в виде одного :) –

+0

Thx для приведенных примеров/предложений. Кажется, что первые два работают на двоих и не более двух опций. Я думаю, что больше может быть достигнуто с использованием настраиваемого объекта, который содержит дополнительные опции. Но это большие накладные расходы. Последние два предложения показывают, что можно связать несколько опций с использованием ifPresent вложенным способом. Таким образом, это решение для данной проблемы, но, к сожалению, читаемость кода уменьшается с каждым добавленным необязательным. Я все равно буду ждать немного, если кто-то найдет другой метод с лучшей читабельностью, иначе я буду принимать это как ответ. – TardigradeX

2

Нет прямого пути.

Stram allMatch будет работать как ifPresent для многих дополнительных опций:

Stream.of(optional1, optional2, ...).allMatch(Optional::isPresent) 
+0

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