JDK8中的 Stream流式編程用法優化(工具類在文章最后)

Java從JDK8起提供了Stream流這個功能,于是項目里出現了大量基于Stream流的寫法。隨著項目的進行,慢慢的代碼中鋪天蓋地的都是下面的寫法:

 List<User> userList = null;if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());}...省略了的業務邏輯...List<User> users = userList.stream().filter(it-> it.getAge() > 28).collect(Collectors.toList());System.out.println(users);

上面的代碼中,構建了一個包含3個User對象的List,然后取出了其中age大于28的User對象構成了新的List。相信如果在日常工作和學習中寫過了大量的類似的代碼,很容易能看出問題來,userList會出現為空的情況,這時候是很容易觸發空指針異常的。所以我們在使用stream前通常都是需要做非空判斷的。于是,優化后的代碼出現了:

List<User> userList = null;
if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());
}...省略了的業務邏輯...
if (userList != null) {List<User> users = userList.stream().filter(it-> it.getAge() > 28).collect(Collectors.toList());System.out.println(users);
}

更近一步,還可以這樣寫:

List<User> userList = null;
if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());
}...省略了的業務邏輯...
List<User> users = Optional.of(userList).orElse(List.of()).stream().filter(it-> it.getAge() > 28).collect(Collectors.toList());
System.out.println(users);

到了這里,這已經是一段比較常規的業務代碼了,但是它真的很丑有沒有。作為一個業務研發人員,我為什么要考慮這么多呢?我不需要關注List是怎么轉換成stream的,同樣的,我也不關心為什么在使用完stream以后還要collect。于是,我將上面的流式代碼封裝成了工具類,上面的代碼可以簡化為:

List<User> userList = null;
if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());
}...省略了的業務邏輯...
List<User> users = Streams.filter(userList, it-> it.getAge() > 28);
System.out.println(users);

同樣的,也支持其他操作:

//返回年齡大于28的用戶列表
List<User> filterUsers = Streams.filter(userList, it -> it.getAge() > 28);//返回年齡大于28的用戶的姓名列表
List<String> filterNames = Streams.toList(userList, it -> it.getAge() > 28, User::getName);//返回年齡大于28的用戶的姓名作為key, 年齡只作為value的map
Map<String, Integer> filterNameAndAgeMap = Streams.toMap(userList, it -> it.getAge() > 28, User::getName, User::getAge);//返回所有用戶的姓名列表
List<String> allUserNames = Streams.toList(userList, User::getName);//返回所有用戶的姓名作為key, 用戶信息只作為value的map
Map<String, User> allUserMap = Streams.mappingToMap(userList, User::getName);//返回所有用戶的姓名作為key, 年齡作為value的map
Map<String, Integer> nameAndAgeMap = Streams.toMap(userList, User::getName, User::getAge);//返回年齡大于28的第一個用戶, 如果找不到則使用默認值
User user = Streams.findFirstOrElse(userList, it-> it.getAge() > 28, new User());//返回年齡大于28的第一個用戶, 如果找不到則拋出異常
User user2 = Streams.findFirstOrThrow(userList, it-> it.getAge() > 28, "未找到符合條件的數據");

最后附上工具類源碼供各位取用:

package com.zlyx.common.util;import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;public class Streams {public static <T> List<T> filter(List<T> dataList, Predicate<T> filter) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).collect(Collectors.toList());}public static <T> Set<T> filter(Set<T> dataList, Predicate<T> filter) {return Optional.of(dataList).orElse(Set.of()).stream().filter(filter).collect(Collectors.toSet());}public static <T> T findFirstOrThrow(List<T> dataList) throws Exception {return findFirstOrThrow(dataList, "未找到符合條件的數據");}public static <T> T findFirstOrThrow(List<T> dataList, String errorMsg) throws Exception {return findFirstOrThrow(dataList, Objects::nonNull, errorMsg);}public static <T> T findFirstOrThrow(List<T> dataList, Predicate<T> filter, String errorMsg) throws Exception {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).findFirst().orElseThrow(() -> new Exception(errorMsg));}public static <T> T findFirstOrElse(List<T> dataList, T defaultValue) {return findFirstOrElse(dataList, Objects::nonNull, defaultValue);}public static <T> T findFirstOrElse(List<T> dataList, Predicate<T> filter, T defaultValue) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).findFirst().orElse(defaultValue);}public static <T, R> R findAnyOrNull(List<T> dataList, Function<T, R> mapper) {return Optional.of(dataList).orElse(List.of()).stream().map(mapper).filter(Objects::nonNull).findAny().orElse(null);}public static <T, R> R findAnyOrThrow(List<T> dataList, Function<T, R> mapper, String errorMsg) throws Exception {return Optional.of(dataList).orElse(List.of()).stream().map(mapper).filter(Objects::nonNull).findAny().orElseThrow(() -> new Exception(errorMsg));}public static <T, R> Set<R> toSet(List<T> dataList, Function<T, R> mapper) {return toSet(dataList, Objects::nonNull, mapper);}public static <T, R> Set<R> toSet(List<T> dataList, Predicate<T> filter, Function<T, R> mapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).map(mapper).collect(Collectors.toSet());}public static <T, R> List<R> toList(List<T> dataList, Function<T, R> mapper) {return toList(dataList, Objects::nonNull, mapper);}public static <T, R> List<R> toList(List<T> dataList, Predicate<T> filter, Function<T, R> mapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).map(mapper).distinct().collect(Collectors.toList());}public static <T, K> Map<K, T> mappingToMap(List<T> dataList, Function<T, K> keyMapper) {return mappingToMap(dataList, Objects::nonNull, keyMapper);}public static <T, K> Map<K, T> mappingToMap(List<T> dataList, Predicate<T> filter, Function<T, K> keyMapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).collect(Collectors.toMap(keyMapper, it -> it, (v1, v2) -> v2));}public static <T, K, V> Map<K, V> toMap(List<T> dataList, Function<T, K> keyMapper, Function<T, V> valueMapper) {return toMap(dataList, Objects::nonNull, keyMapper, valueMapper);}public static <T, K, V> Map<K, V> toMap(List<T> dataList, Predicate<T> filter, Function<T, K> keyMapper, Function<T, V> valueMapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).collect(Collectors.toMap(keyMapper, valueMapper));}
}

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

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

相關文章

uni-app學習筆記十二-vue3中組件傳值(對象傳值)

一.單對象傳值 父組件定義對象的值 <template><view><UserInfo :obj"userinfo"></UserInfo></view> </template><script setup>import {ref} from "vue"const userinfo ref({name:"蛛兒",avatar:&…

UV-python環境管理工具 入門教程

在學習使用 MCP 的時候接觸到了 UV 這個環境管理工具&#xff0c;經過對比&#xff0c;發現它在諸多方面比 venv、conda 等工具更為出色&#xff0c;因此整理了這份簡單的入門學習筆記&#xff0c;希望能幫助大家快速上手。 介紹 UV 是一款集 Python 版本管理、虛擬環境創建與…

【漫話機器學習系列】277.梯度裁剪(Gradient Clipping)

【深度學習】什么是梯度裁剪&#xff08;Gradient Clipping&#xff09;&#xff1f;一張圖徹底搞懂&#xff01; 在訓練深度神經網絡&#xff0c;尤其是 RNN、LSTM、Transformer 這類深層結構時&#xff0c;你是否遇到過以下情況&#xff1a; 模型 loss 突然變成 NaN&#xf…

零基礎弄懂 ngx_http_slice_module分片緩存加速

一、為什么需要 Slice&#xff1f; 在 NGINX 反向代理或 CDN 場景中&#xff0c;大文件&#xff08;視頻、軟件包、鏡像等&#xff09;常因單體體積過大而令緩存命中率低、回源代價高。 ngx_http_slice_module 通過把一次完整響應拆分成 固定大小的字節塊&#xff08;Slice&am…

機器人強化學習入門學習筆記(三)

強化學習&#xff08;Reinforcement Learning, RL&#xff09;與監督學習不同——你不需要預先準備訓練數據集&#xff0c;而是要設計環境、獎勵函數&#xff0c;讓智能體通過交互不斷探索和學習。 &#x1f3af; 一、強化學習和訓練數據的關系 強化學習不依賴固定的數據集。它…

【python實戰】二手房房價數據分析與預測

個人主頁&#xff1a;大數據蟒行探索者 目錄 一、數據分析目標與任務 1.1背景介紹 1.2課程設計目標與任務 1.3研究方法與技術路線 二、數據預處理 2.1數據說明 2.2數據清洗 2.3數據處理 三、數據探索分析 四、數據分析模型 五、方案評估 摘要&#xff1a;隨著社會經…

Kotlin IR編譯器插件開發指南

在 Kotlin 中開發基于 IR&#xff08;Intermediate Representation&#xff09;的編譯器插件&#xff0c;可以深度定制語言功能或實現高級代碼轉換。以下是分步驟指南&#xff1a; 一、IR 編譯器插件基礎 IR 是什么&#xff1f; Kotlin 編譯器將源碼轉換為 IR 中間表示&#xf…

如何用 python 代碼復現 MATLAB simulink 的 PID

MATLAB在 Simulink 里做以下設置MATLAB 腳本調用示例 python 實現離散 PID 實現&#xff08;并行形式&#xff09; Simulink 中兩種 PID 結構&#xff08;并聯形式, I-形式&#xff09;下連續/離散時域里積分增益 I 的表示并聯&#xff08;Parallel&#xff09; vs 理想&#x…

黑馬點評--基于Redis實現共享session登錄

集群的session共享問題分析 session共享問題&#xff1a;多臺Tomcat無法共享session存儲空間&#xff0c;當請求切換到不同Tomcat服務時&#xff0c;原來存儲在一臺Tomcat服務中的數據&#xff0c;在其他Tomcat中是看不到的&#xff0c;這就導致了導致數據丟失的問題。 雖然系…

SkyWalking啟動失敗:OpenSearch分片數量達到上限的完美解決方案

?? 問題現象 SkyWalking OAP服務啟動時報錯: org.apache.skywalking.oap.server.library.module.ModuleStartException: java.lang.RuntimeException: {"error":{"root_cause":[{"type":"validation_exception", "reason&q…

向量數據庫選型實戰指南:Milvus架構深度解析與技術對比

導讀&#xff1a;隨著大語言模型和AI應用的快速普及&#xff0c;傳統數據庫在處理高維向量數據時面臨的性能瓶頸日益凸顯。當文檔經過嵌入模型處理生成768到1536維的向量后&#xff0c;傳統B-Tree索引的檢索效率會出現顯著下降&#xff0c;而現代應用對毫秒級響應的嚴苛要求使得…

MySQL#秘籍#一條SQL語句執行時間以及資源分析

背景 一條 SQL 語句的執行完&#xff0c;每個模塊耗時&#xff0c;不同資源(CPU/IO/IPC/SWAP)消耗情況我該如何知道呢&#xff1f;別慌俺有 - MySQL profiling 1. SQL語句執行前 - 開啟profiling -- profiling (0-關閉 1-開啟) -- 或者&#xff1a;show variables like prof…

【數據結構】實現方式、應用場景與優缺點的系統總結

以下是編程中常見的數據結構及其實現方式、應用場景與優缺點的系統總結&#xff1a; 一、線性數據結構 1. 數組 (Array) 定義&#xff1a;連續內存空間存儲相同類型元素。實現方式&#xff1a;int[] arr new int[10]; // Javaarr [0] * 10 # Python操作&#xff1a; 訪問&…

PyTorch中cdist和sum函數使用示例詳解

以下是PyTorch中cdist與sum函數的聯合使用詳解: 1. cdist函數解析 功能:計算兩個張量間的成對距離矩陣 輸入格式: X1:形狀為(B, P, M)的張量X2:形狀為(B, R, M)的張量p:距離類型(默認2表示歐式距離)輸出:形狀為(B, P, R)的距離矩陣,其中元素 d i j d_{ij} dij?表示…

Ansible配置文件常用選項詳解

Ansible 的配置文件采用 INI 格式&#xff0c;分為多個模塊&#xff0c;每個模塊包含特定功能的配置參數。 以下是ansible.cfg配置文件中對各部分的詳細解析&#xff1a; [defaults]&#xff08;全局默認配置&#xff09; inventory 指定主機清單文件路徑&#xff0c;默認值為 …

了解FTP搜索引擎

根據資料&#xff0c; FTP搜索引擎是專門搜集匿名FTP服務器提供的目錄列表&#xff0c;并向用戶提供文件信息的網站&#xff1b; FTP搜索引擎專門針對FTP服務器上的文件進行搜索&#xff1b; 就是它的搜索結果是一些FTP資源&#xff1b; 知名的FTP搜索引擎如下&#xff0c; …

【大模型面試每日一題】Day 28:AdamW 相比 Adam 的核心改進是什么?

【大模型面試每日一題】Day 28&#xff1a;AdamW 相比 Adam 的核心改進是什么&#xff1f; &#x1f4cc; 題目重現 &#x1f31f;&#x1f31f; 面試官&#xff1a;AdamW 相比 Adam 的核心改進是什么&#xff1f; #mermaid-svg-BJoVHwvOm7TY1VkZ {font-family:"trebuch…

C++系統IO

C系統IO 頭文件的使用 1.使用系統IO必須包含相應的頭文件&#xff0c;通常使用#include預處理指令。 2.頭文件中包含了若干變量的聲明&#xff0c;用于實現系統IO。 3.頭文件的引用方式有雙引號和尖括號兩種&#xff0c;區別在于查找路徑的不同。 4.C標準庫提供的頭文件通常沒…

多模態理解大模型高性能優化丨前沿多模態模型開發與應用實戰第七期

一、引言 在前序課程中&#xff0c;我們系統剖析了多模態理解大模型&#xff08;Qwen2.5-VL、DeepSeek-VL2&#xff09;的架構設計。鑒于此類模型訓練需消耗千卡級算力與TB級數據&#xff0c;實際應用中絕大多數的用戶場景均圍繞推理部署展開&#xff0c;模型推理的效率影響著…

各個網絡協議的依賴關系

網絡協議的依賴關系 學習網絡協議之間的依賴關系具有多方面重要作用&#xff0c;具體如下&#xff1a; 幫助理解網絡工作原理 - 整體流程明晰&#xff1a;網絡協議分層且相互依賴&#xff0c;如TCP/IP協議族&#xff0c;應用層協議依賴傳輸層的TCP或UDP協議來傳輸數據&#…