我想使用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
的方法用于记录
错误。logDetails.size() == 0
答案 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"));