Java 使用 Optionals 对多个属性进行空检查

Java null check on multiple properties with Optionals

java11 上对同一对象的多个字段进行空检查的最有效方法是什么?我正在使用可选项,但我不明白如何将它们用于同一对象的更多字段

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

在我的例子中 getSentdate() returns 具有 getFrom()getTo() 的对象,这些值可能为空也可能不为空

我试过这个,但是在 if 子句中使用 .ifPresent 是一个很大的禁忌

    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;

尝试以下操作,这里 NestedQuery 有一个可选的发送日期,而 SendDate 有可选的 getFrom 和 getTo 值。您可以使用 ifpresent ans 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());
}

虽然使用 && 的条件表达式及其短路行为是您在处理多级属性时可以获得的最佳结果。不过,对于 单层嵌套 ,您可以轻松引入一个实用程序,它符合 none 内部属性为 null。

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

并将其用作

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

请注意,Optional 不参与此操作,通常不需要检查空对象。

正如上面评论中所说,您的原始代码实际上非常有效(我们可能需要一些有效性标准):

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(...)); 

在这种情况下,仅当满足所有 3 个条件时才执行 .ifPresent(date -> nested.put(...))getSentDate() 不是 nullsentDate.getFrom() 不是 nullsentDate.getTo() 也不是 null。然而,我们仍然有一个空检查,我们是 "abusing" Objects#nonNull 方法,因为:

API Note: This method exists to be used as a Predicate, filter(Objects::nonNull)

与此等价的是

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

另请注意,这实际上 "violates" Optional 用法

API Note: Optional is primarily intended for use as a method return type where there is a clear need to represent "no result," and where using null is likely to cause errors.