【问题标题】:Multiple null checks using Optional in Java 8在 Java 8 中使用 Optional 进行多次空检查
【发布时间】:2020-03-19 02:28:46
【问题描述】:

我想使用 Java 8 使用多个 ifelse 语句来简化以下代码。 有没有办法使用一些 Java 8 功能完全摆脱它们,例如Optional? 我试图在这里找到一些东西,但找不到答案。

LocalDateTime beDate = someDate;
LocalDateTime aeDate = someDate;
LocalDateTime eDate;

if (beDate == null && aeDate == null) {
    eDate = null;
}
else if (beDate != null && aeDate == null) {
    eDate = beDate;
}
else if (beDate == null && aeDate != null) {
    eDate =  aeDate;
}
else if (beDate != null && aeDate != null && 
        (beDate.isEqual(aeDate) || beDate.isBefore(aeDate))) {
    eDate = beDate;
}
else {
    eDate = aeDate;
}

【问题讨论】:

  • 我认为您应该不太关心是否可以使用Optional 进行简化,而应该关心一般要简化的内容。请使用大括号。
  • @akuzminykh,用大括号编辑了代码,对此感到抱歉。这是必需的检查。不知道我是否可以进一步简化它。
  • 我建议你嵌套 if-s,外部检查一个日期,内部检查另一个日期。我也觉得你可以提取一些代码作为可重用的方法
  • 我认为前三个检查可以替换为 LocalDateTime eDate = Optional.ofNullable(beDate).orElse(aeDate);您可以继续使用该方法。提示:检查 Optional 的其他方法
  • @IliaNedoluzhko 不完全是,因为如果两者都存在,则该提法不会选择较早的。

标签: java datetime if-statement java-8 optional


【解决方案1】:

这里的逻辑很难理解。相反,更直接地表达你的意图:

private static final Comparator<ChronoLocalDateTime<?>> EARLIEST_PRESENT = 
    Comparator.nullsLast(Comparator.naturalOrder());

LocalDateTime eDate = BinaryOperator.minBy(EARLIEST_PRESENT).apply(beDate, aeDate);

(请注意,静态导入来自ComparatorBinaryOperator 的元素将使这一点更加清晰。)

【讨论】:

  • 这是一个很好的答案,但感觉有点矫枉过正。无论如何,这正是 OP 所要求的。
  • @akuzminykh 对人类的理解可能是代码中最重要的目标。我几乎花了整整一分钟才弄清楚 OP 的代码打算做什么。
  • 罢工就这样结束了吗? :-)
  • @OleV.V.我们拭目以待。我认为自己不会很快达到多个每日限额。
  • return BinaryOperator.minBy(EARLIEST_PRESENT).apply(beDate, aeDate); 虽然我更喜欢a single expression 在这种情况下...
【解决方案2】:

你的条件是多余的,因为结果只是两种可能的结果之一:

if (beDate == null && aeDate == null) {
    eDate = null;
}
else if (beDate != null && aeDate == null) {
    eDate = beDate;
}
...

这里,eDate 将与beDate 具有相同的内容,无论null 与否。所以if(aeDate == null) eDate = beDate; 就足够了。在所有其他情况下,您分配的是aeDate,只有一个例外:

...
else if (beDate != null && aeDate != null && 
        (beDate.isEqual(aeDate) || beDate.isBefore(aeDate))) {
    eDate = beDate;
}
...

我们可以将beDate.isEqual(aeDate) || beDate.isBefore(aeDate) 简化为aeDate.isAfter(beDate)

所以整个语句可以写成:

LocalDateTime eDate
    = aeDate == null || (beDate != null && aeDate.isAfter(beDate))? beDate: aeDate;

|| 是短路的,也就是说,只有当左侧评估为 false 时才评估右侧,所以当左侧为 aeDate == null 时,它暗示右侧手边那个aeDate != null,不需要重复了。

所以当aeDatenull(前两个if 语句)或者当两者都不是nullaeDatebeDate 之后(其他引用if语句),否则获取aeDate的值。

运算符优先级使括号变得不必要,但为了清楚起见,保留它们也是有效的。

【讨论】:

  • 试图重构旧代码,并没有真正看代码背后的逻辑。无论您说什么绝对是有道理的,应该事先检查过。感谢您的帮助,但将使用@chrylis-on-strike 提供的解决方案-
【解决方案3】:

您可以使用Optional.ofNullable,但我不建议这样做。

将所有内容都包含在 Optional 中不会使其更易于阅读。您必须进行null 检查,因此您将obj == null 替换为obj.isEmpty()(或Java 8 中的obj.isEmpty())。

【讨论】:

  • 我希望有办法摆脱许多 if else 语句。有吗?
  • @Pi53 不是我所知道的。这不是Optional的目的。
  • 空检查不是绝对必要的; OP 只是在重塑 Comparator.nullsLast()
【解决方案4】:

您可以使用来自 Apache Commons 的 ObjectUtils::min

LocalDateTime eDate = ObjectUtils.min(aeDate, beDate);

解决方案是一条线,易于阅读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-21
    • 2022-01-16
    • 2023-03-31
    • 2018-03-05
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    • 2017-09-30
    相关资源
    最近更新 更多