Java中關于Optional的 orElse 操作,以及 orElse 與 orElseGet 的區別

文章目錄

      • 1. 大概說明
      • 2. 詳細分析
        • 2.1 .orElse 操作
        • 2.2 .orElse 的作用:避免空指針異常
        • 2.3 為什么要用?
        • 2.4 orElseGet如何使用
        • 2.5 orElse和orElseGet的區別

1. 大概說明

這篇文章的目的是為了說明:

  • orElse 如何使用
  • orElseGet 如何使用
  • 兩者的區別

備注:orElse 可能導致 NullPointerException,當 orElse 的參數是間接計算得來的時候。雖然這種說法有點牽強(因為并不是orElse導致了空指針異常),但是使用 orElseGet 確實可以避免這種情況。

2. 詳細分析

2.1 .orElse 操作

先看個例子:

Optional<String> optional = Optional.empty();
System.out.println(optional.isPresent); // ---->輸出:false
// 返回 false,表示 Optional 里沒有值。

解析:

  • Optional.empty() 代表 一個空的 Optional 實例,即 Optional 沒有值
  • Optional.ofNullable(null) 等價于 Optional.empty()
2.2 .orElse 的作用:避免空指針異常
  • 如果 Optional 為空(即 Optional.empty()),就返回 orElse() 里提供的默認值。
  • 如果 Optional 有值,就直接返回這個值,不執行 orElse() 提供的默認值。

注意:不管 Optional 為不為空,這個值都會創建,只不過為空時,才使用

// 舉例:當Optional為空時,orElse()才會觸發
String result = Optional.ofNullable(null).orElse("默認值");
System.out.println(result); // ---->輸出:默認值
// 再舉個例子:
Map<Long, List<String>> map = new HashMap<>();
map.put(1L, Arrays.asList("A", "B", "C"));List<String> result = Optional.ofNullable(map.get(1L)).orElse(Collections.emptyList()); // 為null就返回 空列表
System.out.println(result);  // ---->輸出:[A, B, C] (orElse() 沒起作用)
2.3 為什么要用?
List<String> result = Optional.ofNullable(map.get(0L)).orElse(Collections.emptyList()).stream();

如果 map.get(0L) == null,那么:

  • 不加 .orElse(Collections.emptyList()).stream() 會報 NullPointerException ?
  • 加了 .orElse(Collections.emptyList()).stream() 能正常執行 ?
2.4 orElseGet如何使用

再來看看 orElseGet 中如何使用:

orElseGet 作用:獲取數據并且設置數據為空時的默認值。如果數據不為空就能獲取到該數據;如果為空則返回傳入的參數來創建對象。

具體的使用案例可看下圖:

在這里插入圖片描述在這里插入圖片描述

2.5 orElse和orElseGet的區別

orElse()orElseGet() 都是Optional 類中的方法,用于在 Optional 為空時提供默認值。但它們的區別在于 默認值的獲取方式

1、orElse(T other)

  • 直接傳遞一個默認值
  • 即使 Optional里有值,也會創建 other 對象,但不會使用它
  • 適用于默認值創建代價較低的情況

2、orElseGet(Supplier<? extends T> supplier)

  • 傳遞的是一個 Supplier(懶加載:只有需要的時候才會創建)接口,它是一個函數式接口,形式是這樣的:()->{ return computedResult },即入參為空,有返回值(任意類型的)
  • 僅當 Optional 為空時才會執行 supplier.get(),不會提前創建默認值
  • 適用于默認值創建代價較高的情況

看個例子:

class User {// 中文名private String chineseName;// 英文名private EnglishName englishName;
}class EnglishName {// 全名private String fullName;// 簡寫private String shortName;
}

假如我們現在有 User 類,用戶注冊賬號時,需要提供自己的中文名或英文名,或都提供,我們抽象出一個EnglishName 類,它包含英文名的全名和簡寫(因為有的英文名確實太長了)。現在,我們希望有一個User.getName() 方法,它可以像下面這樣實現:

class User {// ... 之前的內容public String getName1() {return Optional.ofNullable(chineseName).orElse(englishName.getShortName());}public String getName2() {return Optional.ofNullable(chineseName).orElseGet(() -> englishName.getShortName());}
}

寫了兩個版本,分別使用 orElse 和 orElseGet。現在,你可以看出 getName1() 方法有什么風險了嗎?它會出現空指針異常嗎?----> 是的。當用戶只提供了中文名時,此時 englishName 屬性是 null,但是在 orElse 中,englishName.getShortName()總是會執行。而在 getName2() 中,這個風險卻沒有。

再舉個例子:

public class Test {public static void main(String[] args) {System.out.println("orElse() 的情況:");String result1 = Optional.ofNullable("實際值").orElse(test2());System.out.println("最終結果: " + result1);System.out.println("orElseGet() 的情況:");String result2 = Optional.ofNullable("實際值").orElseGet(() -> test2());System.out.println("最終結果: " + result2);}public static String test2() {System.out.println("執行昂貴的計算...");return "昂貴默認值";}
}

輸出:

orElse() 的情況:
執行昂貴的計算...
最終結果: 實際值orElseGet() 的情況:
最終結果: 實際值

至此,文章結束,記得點贊收藏評論!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898030.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898030.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898030.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據結構-樹(詳解)

目錄 一、樹的基本概念二、樹的節點結構三、樹的基本操作&#xff08;一&#xff09;插入操作&#xff08;二&#xff09;刪除操作&#xff08;三&#xff09;查找操作&#xff08;四&#xff09;遍歷操作 四、樹的實現五、總結 一、樹的基本概念 樹是一種非線性數據結構&…

【eNSP實戰】配置端口映射(NAT Server)

拓圖 要求&#xff1a; 將AR1上的GE 0/0/1接口的地址從TCP協議的80端口映射到內網 Web服務器80端口 AR1接口配置 interface GigabitEthernet0/0/0ip address 192.168.0.1 255.255.255.0 # interface GigabitEthernet0/0/1ip address 11.0.1.1 255.255.255.0 # ip route-s…

RabbitMQ 基本原理詳解

1. 引言 在現代分布式系統中&#xff0c;消息隊列&#xff08;Message Queue&#xff09;是實現異步通信、解耦系統組件、提高系統可靠性和擴展性的重要工具。RabbitMQ 作為一款開源的消息中間件&#xff0c;因其高性能、易用性和豐富的功能&#xff0c;被廣泛應用于各種場景。…

算法——層序遍歷和中序遍歷構造二叉樹

晴問 #include <iostream> #include <vector> #include <queue> #include <unordered_map>using namespace std;struct TreeNode {int data;TreeNode *left;TreeNode *right;TreeNode(int data) : data(data), left(nullptr), right(nullptr) {} };//…

prometheus自定義監控(pushgateway和blackbox)和遠端存儲VictoriaMetrics

1 pushgateway采集 1.1 自定義采集鍵值 如果自定義采集需求時&#xff0c;就可以通過寫腳本 定時任務定期發送數據到 pushgateway 達到自定義監控 1.部署 pushgateway&#xff0c;以 10.0.0.42 節點為例 1.下載組件 wget https://github.com/prometheus/pushgateway/relea…

feign配置重試次數不生效

一、問題產生 自定義重試次數&#xff0c;實現如下 ConditionalOnProperty(prefix "feign.client", name "enable", havingValue "true") Configuration public class FeignConfig {Beanpublic FeignInterceptor feignInterceptor() {retur…

Dify使用部署與應用實踐

最近在研究AI Agent&#xff0c;發現大家都在用Dify&#xff0c;但Dify部署起來總是面臨各種問題&#xff0c;而且我在部署和應用測試過程中也都遇到了&#xff0c;因此記錄如下&#xff0c;供大家參考。Dify總體來說比較靈活&#xff0c;擴展性比較強&#xff0c;適合基于它做…

二叉樹的統一迭代法 標記法

我們以中序遍歷為例&#xff0c;在二叉樹&#xff1a;聽說遞歸能做的&#xff0c;棧也能做&#xff01; (opens new window)中提到說使用棧的話&#xff0c;無法同時解決訪問節點&#xff08;遍歷節點&#xff09;和處理節點&#xff08;將元素放進結果集&#xff09;不一致的情…

BaseActivity 和 BaseFragment 的現代化架構:ViewBinding 與 ViewModel 的深度整合

BaseActivity 和 BaseFragment 實現&#xff0c;集成了 View Binding&#xff0c;并增加了對 Lifecycle 和 ViewModel 的支持&#xff0c;同時進一步簡化了代碼結構&#xff0c;使其更易用、更靈活。 啟用 View Binding 確保在 build.gradle 中啟用了 View Binding&#xff1a…

從零開始學習機器人---如何高效學習機械原理

如何高效學習機械原理 1. 理解課程的核心概念2. 結合圖形和模型學習3. 掌握公式和計算方法4. 理論與實踐相結合5. 總結和復習6. 保持好奇心和探索精神 總結 機械原理是一門理論性和實踐性都很強的課程&#xff0c;涉及到機械系統的運動、動力傳遞、機構設計等內容。快速學習機械…

剖析sentinel的限流和熔斷

sentinel的限流和熔斷 前言源碼分析滑動窗口源碼限流源碼熔斷源碼 完結撒花&#xff0c;sentinel源碼還是挺簡單的&#xff0c;如有需要收藏的看官&#xff0c;順便也用發財的小手點點贊哈&#xff0c;如有錯漏&#xff0c;也歡迎各位在評論區評論&#xff01; 前言 平時發起一…

硬盤分區誤刪后的數據救贖

一、硬盤分區誤刪的概述 硬盤分區誤刪&#xff0c;是許多電腦用戶在使用過程中可能遭遇的棘手問題。分區&#xff0c;作為硬盤上存儲數據的邏輯單元&#xff0c;一旦被誤刪除&#xff0c;不僅會導致該分區內的所有數據瞬間消失&#xff0c;還可能影響到整個硬盤的存儲結構和數…

代碼隨想錄算法訓練營第三十五天(20250303) |01背包問題 二維,01背包問題 一維,416. 分割等和子集 -[補卡20250316]

01背包問題 二維 鏈接 遍歷物品沒有大小順序要求重點是模擬&#xff0c;推導出遞推公式 #include <iostream> #include <vector>int main(){int m, n;std::cin>>m>>n;std::vector<int> weight(m,0),value(m,0);for(int i{0}; i<m; i){std:…

老牌軟件,方便處理圖片,量大管飽。

今天介紹的圖片查看器名字是&#xff1a;FastStone Image Viewer&#xff0c;是一款可查看、編輯、批量重命名、批量轉換的圖片查看軟件。文末有分享鏈接。 軟件以資源管理器的方式管理你電腦里的圖片&#xff0c;點擊左側可選擇文件夾&#xff0c;右邊可預覽圖片。 軟妹用得最…

【數據庫相關】mysql數據庫巡檢

mysql數據庫巡檢 巡檢步驟**一、基礎狀態檢查****二、服務器資源監控****CPU使用****內存使用****磁盤I/O****網絡流量** **三、數據庫內部健康度****全局狀態****慢查詢監控****鎖與并發** **四、存儲引擎健康****InnoDB引擎****MyISAM引擎** **五、日志與備份****六、安全與權…

Python進階編程總結

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;…

Redis復制(replica)主從模式

Redis主從復制 Redis 的復制&#xff08;replication&#xff09;功能允許用戶根據一個 Redis 服務器來創建任意多個該服務器的復制品&#xff0c;其中被復制的服務器為主服務器&#xff08;master&#xff09;&#xff0c;而通過復制創建出來的服務器復制品則為從服務器&#…

Adobe Premiere Pro2023配置要求

Windows 系統 最低配置 處理器&#xff1a;Intel 第六代或更新版本的 CPU&#xff0c;或 AMD Ryzen? 1000 系列或更新版本的 CPU&#xff0c;需要支持 Advanced Vector Extensions 2&#xff08;AVX2&#xff09;。操作系統&#xff1a;Windows 10&#xff08;64 位&#xff…

【Kubernets】Deployment 和 StatefulSet 有什么區別?什么時候用 StatefulSet?

Deployment 和 StatefulSet 的區別 在 Kubernetes 中&#xff0c;Deployment 和 StatefulSet 都用于管理 Pod&#xff0c;但它們適用于不同的場景。 1. Deployment&#xff1a;管理無狀態應用 特點&#xff1a; 無狀態&#xff1a;Pod 之間相互獨立&#xff0c;不需要保持順…

R語言零基礎系列教程-03-RStudio界面介紹與關鍵設置

代碼、講義、軟件回復【R語言03】獲取。 設置位置: 菜單欄 - Tools - Blobal Options 設置 通用設置 設置面板左側General選項 版本選擇: 一般只用一個版本即可 默認工作目錄設置: 你希望RStudio打開時是基于哪個目錄進行工作可以不設置, 因為腳本一般都是放置在特定項目路…