如何使用 Java Optional 优雅地替换三元运算符

     2023-02-23     143

关键词:

【中文标题】如何使用 Java Optional 优雅地替换三元运算符【英文标题】:How to use Java Optional to elegantly replace Ternary operators 【发布时间】:2019-04-12 12:37:13 【问题描述】:

一个超级简单的问题:

这是我使用传统三元运算符 ? 的纯 Java 代码

public DateTime getCreatedAt() 
    return !recordA.isPresent() ? recordB.get().getCreatedAt() : recordA.get().getCreatedAt();

我最好的选择是:

public DateTime getCreatedAt() 
    return recordA.map(
        record -> record.getCreatedAt())
        .orElse(recordB.get().getCreatedAt());
  

这可以编译,但看起来它的行为不正确。 它总是执行两个分支,例如当recordA isPresent() 时,它仍然执行recordB.get().getCreatedAt() 这抛出了我

java.util.NoSuchElementException: No value present

感谢任何帮助!

基本上,我想用更高级的 Optional/lamda 功能替换传统的三元运算符。

【问题讨论】:

.orElseGet(() -> recordB.get().getCreatedAt()); ? 你需要orElseGet。您还可以使用两个选项和or() recordB 也是可选的吗? 看我的回答如果它是空的如何处理。 Optional 不应该以这种方式使用。我的意思是,如果你愿意,你可以像这样使用它,毕竟它是你的代码 :) 但我的意思是,它不是为了替换三元运算符或 if/else 语句而设计的。它的主要用途是作为一个返回类型,在 youtube Stuart Marks 的会议上讨论这个话题。您可以像这样改进您的实际代码:return (recordA.isPresent() ? recordA : recordB).get().getCreatedAt() 【参考方案1】:

为避免急切地评估 else 分支,请使用 orElseGet,它采用函数接口 Supplier 的实例:

return recordA.map(
    record -> record.getCreatedAt())
    .orElseGet(() -> recordB.get().getCreatedAt());

【讨论】:

如果recordArecordB属于同一类型,可以简写为recordA.orElseGet(recordB::get).getCreatedAt() @Andreas 在recordB 为空Optional 时不起作用。 @tsolakp 它与问题和这个答案完全相同,即如果recordArecordB 都是空的,所有3 个都会抛出异常。 @Andreas。如果recordArecordB 为空,则不确定OP 是否想要异常。 @tsolakp 但是你为什么要解决我的评论,好像我评论的代码是唯一有问题的代码?也解决答案,因为它有同样的问题。更好的是,对问题写评论,通知 OP 潜在问题,并询问它是否是一个问题。也许逻辑是它们中至少有一个是非空的,这使它成为非问题。这当然不是我建议的较短代码引入的问题,就像我写 orElse(recordB.get()) 时那样,但这不是我写的。【参考方案2】:

我关于recordBOptional 的问题没有得到解答,但如果它是Optional,那么你不能安全地调用它的get 方法,你需要检查它是否为空。如果recordArecordB 都为空Otionals,则此处安全调用以获取记录或null。

        recordA
            .map(Record::getCreatedAt)
            .orElseGet( () -> recordB.map(Record::getCreatedAt).orElse(null) );

【讨论】:

我在第二部分看不到Optional 的用途。创建一个Optional 只是为了调用orElse(null) 是一种已知的反模式。 我同意。但是我们正在 OP 提供的示例中工作。理想情况下,getCreatedAt 也应该返回Optional,或者在我的回答中至少使用DateTime 的某种默认值而不是null【参考方案3】:

您正在寻找.orElseGet(() -> recordB.get().getCreatedAt());,可以在这篇文章中找到原因 --> Difference between Optional.orElse() and Optional.orElseGet()

有些人可能会觉得它有点主观,但我个人认为,默认情况下,每次使用 orElseGet() 比使用 orElse 更有意义,除非默认对象已经构造为这将防止您现在面临的许多意外问题(假设您没有阅读 orElse 和 orElseGet doc 之间的区别)。

阅读更多来自Java Optional – orElse() vs orElseGet()

【讨论】:

【参考方案4】:

如果您使用的是 Java 9+,则可以使用 ifPresentOrElse() 方法 as more completely explained in this *** answer。

recordA.ifPresentOrElse(
   value -> recordA.get().getCreatedAt(),
   () -> recordB.get().getCreatedAt()
);

【讨论】:

没用java8,怎么优雅地避免空指针?

...哥https://blog.csdn.net/u012881904/article/details/68935009JDK8里面有Optional,如果你还在使用JDK7及之前的版本,那么可以使用Google的Guava库,用法差不多,下面介绍一下Google的Guava库用法。为什么使用?GoogleGuavaOptional使用Optional除了简化粗鲁的... 查看详情

java8optional:优雅地避免npe

本篇文章将详细介绍Optional类,以及如何用它消除代码中的null检查。在开始之前首先来看下什么是NPE,以及在Java8之前是如何处理NPE问题的。空指针异常(NullPointException,简称NPE)可以说是所有Java程序员都遇到过的一个异常,虽... 查看详情

使用optional更优雅地处理非空判断(代码片段)

...这样就会显得代码特别繁琐。这篇文章就带你用JDK8中的Optional来解决空指针异常。(二)什么是OptionalOptional类是Java8的新特性,是一个可以为null的容器对象,Optional的使用很简单,介绍几种常用的方法:Opt... 查看详情

使用optional更优雅地处理非空判断(代码片段)

(一)引言在平常的编码之中,有一个错误总会在你的意料之外出现,那就是空指针异常。空指针的出现也很简单,你得到了一个null对象,调用了一些方法,出现空指针异常。空指针会出现在各种地方... 查看详情

如何更好地使用java8的optional

Java8中的Optional<T>是一个可以包含或不可以包含非空值的容器对象,在 StreamAPI中很多地方也都使用到了Optional。  java中非常讨厌的一点就是nullpoint,碰到空指针就会出错抛Exception,然后需要逐行检查是哪个对象为空,... 查看详情

如何在swift中优雅地使用uiimage

...object:Dictionary<String,JSONValue>?注意每一种属性都是一个Optional值。这是因为JSON数据能包含任何它定义的有效类型。因此,建议的方式是用Optional绑定检索值 查看详情

guava学习笔记:optional优雅的使用null

在我们学习和使用Guava的Optional之前,我们需要来了解一下Java中null。因为,只有我们深入的了解了null的相关知识,我们才能更加深入体会领悟到Guava的Optional设计和使用上的优雅和简单。   null代表不确定的对象:  Jav... 查看详情

如何更好地使用java8的optional

参考技术AJava8Optional包含或包含非空值容器象StreamAPI都使用Optional  java非讨厌点nullpoint碰空指针错抛Exception需要逐行检查哪象空带量必要精力损耗抛NPE错误用户操作错误发员错误应该避免能每加入非空检查阅读性维护性都比较... 查看详情

用 UIPickerView 优雅地替换 iPhone 键盘

...DateCell示例所示。大多数情况下它可以工作,但我不知道如何 查看详情

在vim中优雅地查找和替换

...级强的查找!这篇文章来详细介绍Vim中查找相关的设置和使用方法。包括查找与替换、查找光标所在词、高亮前景/背景色、切换高亮状态、大小写敏感查找等。查找在normal模式下按下/即可进入查找模式,输入要查找的字符串并... 查看详情

如何优雅地使用ios系统相机相册

如何优雅地使用iOS系统相机、相册概述iOS系统相机、相册功能全部依托于图像选取控制器UIImagePickerController,在使用该控制器时,我们需要按照如下步骤进行检查指定的资源类型是否可用检查指定资源类型下是否支持指定的媒体类... 查看详情

如果优雅地关闭executorservice提供的java线程池

...资源,因此线程池的关闭与清理同样重要,本文介绍我们如何优雅地关闭线程池。一.ExecutorService中关闭线程池的方法1.shutdown()停止接收新任务,原来的任务继续执行停止接收新的subm 查看详情

「springboot」如何优雅地管理springboot项目

本文主要讲述一下如何优雅地管理SpringBoot项目。背景课堂上,当小明形如流水地回答完沐芳老师提出来的问题时,却被至今没有对象的胖虎无情嘲讽了?沐芳老师:小明,你平时是如何启动、停止你的SpringBoot项目的?小明(自... 查看详情

在vim中优雅地查找和替换vi

...级强的查找!这篇文章来详细介绍Vim中查找相关的设置和使用方法。包括查找与替换、查找光标所在词、高亮前景/背景色、切换高亮状态、大小写敏感查找等。查找在normal模式下按下/即可进入查找模式,输入要查找的字符串并... 查看详情

如何优雅地使用sublimetext

如何优雅地使用SublimeTextBy 晚晴幽草轩轩主发表于2015-12-15SublimeText:一款具有代码高亮、语法提示、自动完成且反应快速的编辑器软件,不仅具有华丽的界面,还支持插件扩展机制,用她来写代码,绝对是一种享受。相比于... 查看详情

如何优雅地使用sublimetext

...感无比的编辑器是Coding和Writing最佳的选择,没有之一。如何优雅地使用 查看详情

优雅地把html解析为java/kotlin实体对象

使用Java如何优雅地爬取网页内容,并解析为实体对象呢?由于我对Android平台比较熟悉,在项目中我们使用的Retrofit、Okhttp、Kotlin协程、LoganSquare解析把Server返回的Json解析为实体对象。那爬网页的时候是不是也可以使... 查看详情

java示例代码_在Java/Spring中,如何优雅地处理缺失的翻译值

java示例代码_在Java/Spring中,如何优雅地处理缺失的翻译值 查看详情