Java проверка на null для нескольких свойств с помощью Optionals - PullRequest
3 голосов
/ 23 апреля 2020

Какой самый эффективный способ на java 11 проверять на ноль несколько полей одного и того же объекта? Я собирался с опциями, но я не понимаю, как использовать их с несколькими полями одного и того же объекта

    Map<String, NestedQuery> nested = new HashMap<>();
    if (getSentDate() != null) {
      if (getSentDate().getFrom() != null && getSentDate().getTo() != null) {
        nested.put(...); 
      }
    }
    return nested;

В моем случае getSentdate() возвращает объект с getFrom() и getTo(), который являются значениями, которые могут быть или не быть нулевыми

Я пытался с этим, но использование .ifPresent внутри предложения if является большим нет нет

    Map<String, NestedQuery> nested = new HashMap<>();
    Optional.ofNullable(getSentDate())
        .ifPresent(sentDate -> {
          Optional<String> from = Optional.ofNullable(sentDate.getFrom());
          Optional<String> to = Optional.ofNullable(sentDate.getTo());
          if(from.isPresent() && to.isPresent()){
            nested.put(...);
          }
        });
    return nested;

Ответы [ 3 ]

2 голосов
/ 28 апреля 2020

Как было сказано в комментариях выше, ваш исходный код на самом деле достаточно эффективен (нам, вероятно, нужны некоторые критерии эффективности):

if (getSentDate() != null) {
      if (getSentDate().getFrom() != null && getSentDate().getTo() != null) {

Однако, если вы действительно хотите использовать Optional для исключить некоторые из нулевых проверок, достаточно использовать только одну:

Optional.ofNullable(getSentDate())
        .filter(sentDate -> Objects.nonNull(sentDate.getFrom()))
        .filter(sentDate -> Objects.nonNull(sentDate.getTo())) 
        .ifPresent(date -> nested.put(...)); 

, в этом случае .ifPresent(date -> nested.put(...)) выполняется только при соблюдении всех 3 условий: getSentDate() не null, sentDate.getFrom() не null и sentDate.getTo() также не null. Однако у нас все еще есть нулевая проверка, и мы «злоупотребляем» Objects # nonNull методом, так как:

API Примечание: Этот метод существует для использования в качестве Предиката, фильтра (Объекты :: nonNull)

Эквивалентом этого является

Optional.ofNullable(getSentDate())
        .filter(sentDate -> sentDate.getFrom() != null)
        .filter(sentDate -> sentDate.getTo() != null) 
        .ifPresent(date -> nested.put(...)); 

Также обратите внимание, что это на самом деле "нарушает" Необязательно использование

API Примечание: Optional предназначен в первую очередь для использования в качестве типа возврата метода, где существует явная необходимость представлять «нет результата», и где использование null может вызвать ошибки.

0 голосов
/ 23 апреля 2020

Хотя условное выражение с использованием && и его поведение при коротком замыкании - лучшее, что вы можете получить при работе с несколькими уровнями атрибутов. Тем не менее, для одного уровня вложенности , вы можете легко представить утилиту, которая не соответствует ни одному из атрибутов внутри, равных нулю.

@SafeVarargs
static <T> boolean noneNull(T... args) {
    return Arrays.stream(args).noneMatch(Objects::isNull);
}

и использовать ее как

if(noneNull(sentDate.getFrom(), sentDate.getTo())) {
    nested.put(...)
}

и обратите внимание, что Optional для этого не требуется, что обычно не требуется для проверки нулевых объектов.

0 голосов
/ 23 апреля 2020

Попробуйте следующее: здесь NestedQuery имеет необязательную дату отправки, а SendDate имеет необязательные значения getFrom и getTo. Вы можете использовать ifpresent и ispresent для проверки наличия значения

private interface SendDate {

Optional<Object> getFrom();

Optional<Object> getTo();
}

private interface NestedQuery {

public Optional<SendDate> getSendDate();
}

private static NestedQuery createNestedQuery() {
return Optional::empty;
}

public static void main(final String[] args) {
final Map<String, NestedQuery> nested = new HashMap<>();
final NestedQuery nestedQuery = createNestedQuery();
nestedQuery.getSendDate().ifPresent(sendDate -> {
    if (sendDate.getFrom().isPresent() && sendDate.getTo().isPresent())
    nested.put("", nestedQuery);
});
System.out.println(nested.toString());
}
...