使用Optional.orElseGet做一些记录逻辑是个好主意吗

时间:2019-01-20 00:56:24

标签: java

我想使用Optional来处理null值,而我想不出最好的处理方式的“棘手”部分是:我想在value为null时进行记录。我可以使用以下代码实现这一点-但感觉很尴尬。

(更新:我已经发布了自己的答案,Java 9中的Optional)

让我们说代码看起来像这样:

// logLine.getSomeProperty returns Optional<String>

List<LogDetails> logDetails = logLine.getSomeProperty()
    .map(this::extractLogDetails)
    .orElseGet(() -> logError(logLine));
List<LogDetails> extractLogDetails(String s) {
    List<LogDetails> logDetails = new ArrayList<>();
    String sp = "(?:([A-Z0-9]{5,7})-([A-Z0-9]{9})-(.{4}))"; 
    Pattern p = Pattern.compile(sp, Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(s);
    while (m.find()) {
        logDetails.add(new LogDetails(m.group(1), m.group(2), m.group(3)));
    }
    return logDetails;
}
  
List<LogDetails> logError(LogLine logLine) {
    log.error("Error while ... {} ", logLine));
    persistence.setErrorStatus(logLine, FAILED_PARSING);
    return new ArrayList<>();
}

它可以做我想要的,但是我有几个“问题”。

  • 我发现这很奇怪,称为orElseGet的方法用于记录 错误。
  • 我可以在其中用orElseThrow和logError替换orElseGet,不要扔任何东西-我也不喜欢。
  • logError方法返回我不使用的List,从方法中返回应该为空的东西看起来很奇怪。
  • 只是必须有更好的方法
  • 在someProperty不为null但没有匹配的情况下-我也想登录,但是为此,我需要另一行代码来检查logDetails.size() == 0

3 个答案:

答案 0 :(得分:2)

orElseGet并不是真正的错误处理机制,而是在Optional实例不携带任何默认值的情况下生成不同默认值的一种方法。

如果要检查Optional是否明确为空,只需使用Optional.isPresent()检查,然后在这种情况下执行logError()

首先需要考虑的是,如果Optional为空,您想做什么?除了记录错误之外,您是否要继续空白列表?

如果是,那么您可能会遇到类似这样的事情:

List<LogDetails> logDetails = logLine.getSomeProperty()
    .map(this::extractLogDetails)
    .orElseGet(Collections::emptyList);

之后,您可以执行以下操作:

if (logDetails.isEmpty()) {
  logError(logline);
}

或者,如果您根本不想有一个空列表,则可以将其保持在可选级别。这样,getSomeProperty()为空或生成的列表为空的两种情况都以相同的方式处理。

Optional<List<LogDetails>> logDetailsOpt = logLine.getSomeProperty() 
                       .map(this::extractLogDetails)
                       .filter(list -> !list.isEmpty());

if (!logDetailsOpt.isPresent()) {
  logError(logLine);
}

在两种情况下,logError()均不会返回任何内容。它正在按照其名称执行预期的操作,并记录错误。

与其尝试过度使用Optional的功能,不如使您的代码意图明确。可读性更具价值。

答案 1 :(得分:1)

您无需更改结果类型或在流中进行记录,而只需返回分区的Map。然后,在获得结果后,在结果图上执行日志功能。

 Map<Boolean, List<String>> map = Stream.of("a", "aaa", "aaaa")
           ----
                .collect(() -> Collectors.partitioningBy(predicate))
           ----

答案 2 :(得分:0)

虽然我很感谢这些答案,但是最近才发现Java 9向Optional引入了新方法,我最喜欢它。 这是示例。

Optional.ofNullable(user).ifPresentOrElse( u -> logger.info("User is:" + u.getEmail()),
  () -> logger.info("User not found"));