Java Stream API詳解:高效處理集合數據的利器

引言

Java 8引入了許多新特性,其中最為顯著的莫過于Lambda表達式和Stream API。Stream API提供了一種高效、簡潔的方法來處理集合數據,使代碼更加簡潔明了,且具有較高的可讀性和可維護性。本文將深入探討Java Stream API的使用,包括基礎概念、常用操作、并行處理、實戰案例以及最佳實踐等內容。

目錄

  1. 什么是Stream API
  2. Stream API的基礎操作
    • 創建Stream
    • 中間操作
    • 終端操作
  3. Stream API的高級操作
    • 排序
    • 篩選
    • 映射
    • 規約
    • 收集
  4. 并行Stream
  5. Stream API實戰案例
    • 處理集合數據
    • 文件操作
    • 數據庫操作
  6. Stream API的最佳實踐
  7. 常見問題與解決方案
  8. 總結

什么是Stream API

Stream API是Java 8引入的一種用于處理集合數據的抽象,它允許以聲明性方式(類似SQL語句)來處理數據。Stream API提供了許多強大的操作,可以用來對集合進行過濾、排序、映射、規約等操作,極大地簡化了代碼。

特點

  • 聲明性編程:使用Stream API可以以聲明性的方式編寫代碼,減少樣板代碼。
  • 鏈式調用:Stream API的操作可以鏈式調用,提高代碼的可讀性。
  • 惰性求值:中間操作是惰性求值的,只有在執行終端操作時才會進行計算。
  • 并行處理:支持并行處理,可以充分利用多核CPU的優勢。

Stream API的基礎操作

創建Stream

Stream API提供了多種方式來創建Stream,常見的有以下幾種:

  1. 從集合創建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
  1. 從數組創建
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
  1. 使用Stream.of
Stream<String> stream = Stream.of("a", "b", "c");
  1. 使用Stream.generate
Stream<Double> stream = Stream.generate(Math::random).limit(10);
  1. 使用Stream.iterate
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(10);

中間操作

中間操作用于轉換Stream,是惰性求值的,常見的中間操作有以下幾種:

  1. filter:用于過濾元素。
Stream<String> stream = list.stream().filter(s -> s.startsWith("a"));
  1. map:用于映射每個元素到對應的結果。
Stream<String> stream = list.stream().map(String::toUpperCase);
  1. flatMap:用于將每個元素轉換為Stream,然后合并成一個Stream。
Stream<String> stream = list.stream().flatMap(s -> Stream.of(s.split("")));
  1. distinct:用于去重。
Stream<String> stream = list.stream().distinct();
  1. sorted:用于排序。
Stream<String> stream = list.stream().sorted();
  1. peek:用于在處理過程中查看每個元素。
Stream<String> stream = list.stream().peek(System.out::println);

終端操作

終端操作用于啟動Stream的計算,并生成結果,常見的終端操作有以下幾種:

  1. forEach:對每個元素執行操作。
list.stream().forEach(System.out::println);
  1. collect:將Stream轉換為其他形式。
List<String> result = list.stream().collect(Collectors.toList());
  1. reduce:將Stream中的元素規約成一個值。
Optional<String> result = list.stream().reduce((s1, s2) -> s1 + s2);
  1. toArray:將Stream轉換為數組。
String[] array = list.stream().toArray(String[]::new);
  1. count:計算元素個數。
long count = list.stream().count();
  1. anyMatchallMatchnoneMatch:用于匹配判斷。
boolean anyMatch = list.stream().anyMatch(s -> s.startsWith("a"));
boolean allMatch = list.stream().allMatch(s -> s.startsWith("a"));
boolean noneMatch = list.stream().noneMatch(s -> s.startsWith("a"));
  1. findFirstfindAny:用于查找元素。
Optional<String> first = list.stream().findFirst();
Optional<String> any = list.stream().findAny();

Stream API的高級操作

排序

使用sorted方法對Stream進行排序,可以傳入一個比較器。

List<String> list = Arrays.asList("b", "c", "a");
List<String> sortedList = list.stream().sorted().collect(Collectors.toList());
// 逆序排序
List<String> sortedListDesc = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

篩選

使用filter方法對Stream中的元素進行篩選。

List<String> list = Arrays.asList("a", "b", "c");
List<String> filteredList = list.stream().filter(s -> s.startsWith("a")).collect(Collectors.toList());

映射

使用map方法對Stream中的元素進行映射。

List<String> list = Arrays.asList("a", "b", "c");
List<String> mappedList = list.stream().map(String::toUpperCase).collect(Collectors.toList());

規約

使用reduce方法對Stream中的元素進行規約。

List<String> list = Arrays.asList("a", "b", "c");
String result = list.stream().reduce("", (s1, s2) -> s1 + s2);

收集

使用collect方法將Stream轉換為其他形式。

List<String> list = Arrays.asList("a", "b", "c");
List<String> collectedList = list.stream().collect(Collectors.toList());
Set<String> collectedSet = list.stream().collect(Collectors.toSet());
String joinedString = list.stream().collect(Collectors.joining(","));

并行Stream

并行Stream可以充分利用多核CPU的優勢,提高數據處理的效率。可以使用parallelStream方法創建并行Stream。

List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.parallelStream().map(String::toUpperCase).collect(Collectors.toList());

也可以使用parallel方法將普通Stream轉換為并行Stream。

List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.stream().parallel().map(String::toUpperCase).collect(Collectors.toList());

需要注意的是,并行Stream并不是總是比串行Stream更快,具體需要根據具體情況進行測試。

Stream API實戰案例

處理集合數據

案例一:過濾并轉換集合

給定一個包含若干字符串的集合,過濾掉長度小于3的字符串,并將剩余字符串轉換為大寫。

List<String> list = Arrays.asList("a", "ab", "abc", "abcd");
List<String> result = list.stream().filter(s -> s.length() >= 3).map(String::toUpperCase).collect(Collectors.toList());
System.out.println(result); // 輸出:[ABC, ABCD]
案例二:計算平均值

給定一個包含若干整數的集合,計算所有整數的平均值。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
OptionalDouble average = list.stream().mapToInt(Integer::intValue).average();
average.ifPresent(System.out::println); // 輸出:3.0

文件操作

案例三:讀取文件內容

使用Stream API

讀取文件內容并輸出到控制臺。

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {lines.forEach(System.out::println);
} catch (IOException e) {e.printStackTrace();
}
案例四:統計單詞出現次數

讀取文件內容并統計每個單詞出現的次數。

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {Map<String, Long> wordCount = lines.flatMap(line -> Arrays.stream(line.split("\\W+"))).collect(Collectors.groupingBy(String::toLowerCase, Collectors.counting()));wordCount.forEach((word, count) -> System.out.println(word + ": " + count));
} catch (IOException e) {e.printStackTrace();
}

數據庫操作

案例五:處理數據庫查詢結果

假設我們有一個數據庫表users,包含字段idnameage。我們可以使用Stream API處理查詢結果。

List<User> users = queryDatabase();
List<String> names = users.stream().filter(user -> user.getAge() > 18).map(User::getName).collect(Collectors.toList());
System.out.println(names);

Stream API的最佳實踐

  1. 避免不必要的并行化:并行Stream并不是總是更快,應該根據具體情況進行選擇。
  2. 合理使用中間操作和終端操作:中間操作是惰性求值的,只有在執行終端操作時才會進行計算。
  3. 注意Stream的可復用性:Stream一旦被消費就不能再使用,如果需要復用,可以考慮將Stream轉換為集合再使用。
  4. 使用合適的收集器Collectors類提供了多種收集器,可以根據具體需求選擇合適的收集器。
  5. 處理異常:在使用Stream API時,需要處理可能出現的異常,尤其是在文件操作和數據庫操作中。

常見問題與解決方案

Stream已關閉

Stream一旦被消費就不能再使用,如果需要復用,可以考慮將Stream轉換為集合再使用。

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println); // 會拋出IllegalStateException

性能問題

并行Stream并不是總是比串行Stream更快,具體需要根據具體情況進行測試。可以使用ForkJoinPool來優化并行Stream的性能。

ForkJoinPool customThreadPool = new ForkJoinPool(4);
customThreadPool.submit(() ->list.parallelStream().forEach(System.out::println)
).get();

內存泄漏

在使用Stream API處理大數據量時,需要注意內存泄漏的問題。可以使用close方法關閉Stream,或者使用try-with-resources語句自動關閉Stream。

try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {lines.forEach(System.out::println);
} catch (IOException e) {e.printStackTrace();
}

總結

本文詳細介紹了Java Stream API的使用,包括基礎操作、高級操作、并行處理、實戰案例以及最佳實踐等內容。通過合理利用Stream API,開發者可以大大簡化代碼,提高代碼的可讀性和可維護性,同時還可以提高數據處理的效率。希望本文對你在Java開發中的Stream API使用有所幫助。

Java Stream API是處理集合數據的強大工具,通過靈活運用各種操作,可以實現高效的數據處理和流式計算。如果你還沒有使用過Stream API,建議盡快學習和掌握這一強大的工具,將其應用到你的項目中,提升開發效率和代碼質量。

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

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

相關文章

QFileDialog的簡單了解

ps&#xff1a;寫了點垃圾&#xff08;哈哈哈&#xff09; 它繼承自QDialog 這是Windows自己的文件夾 這是兩者的對比圖&#xff1a; 通過看QFileDialog的源碼&#xff0c;來分析它是怎么實現這樣的效果的。 源碼組成&#xff1a; qfiledialog.h qfiledialog_p.h&#xff…

Python面試寶典第11題:最長連續序列

題目 給定一個未排序的整數數組 nums &#xff0c;找出數字連續的最長序列&#xff08;不要求序列元素在原數組中連續&#xff09;的長度。請你設計并實現時間復雜度為 O(n) 的算法解決此問題。 示例 1&#xff1a; 輸入&#xff1a;nums [100,4,200,1,3,2] 輸出&#xff1a;…

微信小程序中的數據通信

方法1: 使用回調函數 在app.js中:可以在修改globalData后執行一個回調函數,這個回調函數可以是頁面傳遞給app的一個更新函數。// app.js App({globalData: {someData: ,},setSomeData(newData, callback) {this.globalData.someData = newData;if (typeof callback === funct…

打造熱銷爆款:LazadaShopee店鋪測評與關鍵詞策略

面對Lazada和Shopee平臺上店鋪銷量難以突破的困境&#xff0c;賣家們往往尋求各種解決方案。其中&#xff0c;店鋪測評作為提升店鋪信譽、優化產品排名及增加曝光度的有效手段&#xff0c;正逐漸成為賣家關注的焦點。以下將深入探討店鋪測評的好處、實施技巧及自養號的關鍵要素…

提升校園效率:智慧校園后勤管理中的尋物管理功能

在智慧校園后勤管理體系中&#xff0c;尋物管理功能扮演著連接遺失與找回的橋梁角色&#xff0c;它充分利用現代信息技術&#xff0c;為校園內的師生提供了一套高效、便捷的失物招領解決方案。此功能圍繞以下幾個核心方面展開。 首先&#xff0c;它支持在線報失與信息登記。一旦…

如何連接到公司的服務器?

1.下載FileZilla FileZilla的下載與安裝以及簡單使用&#xff08;有圖解超簡單&#xff09;-CSDN博客 2.打開 3.輸入主機 用戶名 密碼 端口 注&#xff1a;主機支持的協議類型&#xff1a; 4.連接成功 其他方式也有很多&#xff0c;比如通過cmd&#xff0c;html網頁等等 3個…

昇思25天學習打卡營第19天|ShuffleNet圖像分類

今天是參加昇思25天學習打卡營的第19天&#xff0c;今天打卡的課程是“ShuffleNet圖像分類”&#xff0c;這里做一個簡單的分享。 1.簡介 在第15-18日的學習內容中&#xff0c;我們陸陸續續學習了計算機視覺相關的模型包括圖像語義分割、圖像分類、目標檢測等內容&#xff0c…

面試遲到了怎么辦

嗨&#xff0c;我是蘭若姐姐。作為一名面試官&#xff0c;最近面試了很多的測試候選人&#xff0c;有了很多感慨&#xff0c;借此抒發一下&#xff0c;我不知道別人面試更看重的是什么&#xff0c;但是在我這里&#xff0c;我最看重的是態度&#xff0c;其次才是技能 我覺得作…

vivado EXTRACT_ENABLE、EXTRACT_RESET

可提取 EXTRACT_ENABLE控制寄存器推斷是否啟用。通常&#xff0c;Vivado工具 提取或不提取基于啟發式方法&#xff0c;通常有利于最大程度的 設計。如果Vivado的行為不符合預期&#xff0c;此屬性將覆蓋 工具的默認行為。如果有不希望的啟用連接到CE引腳 觸發器&#xff0c;此屬…

中關村軟件園發布“數據合規與出境評估服務平臺”

在2024中關村論壇年會期間&#xff0c;中關村軟件園發布“數據合規與出境評估服務平臺”。該平臺是中關村軟件園結合北京市“兩區”建設&#xff0c;立足軟件園國家數字服務出口基地和數字貿易港建設&#xff0c;圍繞園區內外部企業用戶的業務合作、科研創新、跨國運營等場景需…

Python UDP編程之實時聊天與網絡監控詳解

概要 UDP(User Datagram Protocol,用戶數據報協議)是網絡協議中的一種,主要用于快速、簡單的通信場景。與TCP相比,UDP沒有連接、確認、重傳等機制,因此傳輸效率高,但也不保證數據的可靠性和順序。本文將詳細介紹Python中如何使用UDP協議進行網絡通信,并包含相應的示例…

七天.NET 8操作SQLite入門到實戰 - 第一天 SQLite 簡介

什么是SQLite&#xff1f; SQLite是一個輕量級的嵌入式關系型數據庫&#xff0c;它以一個小型的C語言庫的形式存在。它的設計目標是嵌入式的&#xff0c;而且已經在很多嵌入式產品中使用了它&#xff0c;它占用資源非常的低&#xff0c;在嵌入式設備中&#xff0c;可能只需要幾…

Vscode插件推薦——智能切換輸入法(Smart IME)

前言 相信廣大程序員朋友在寫代碼的時候一定會遇到過一個令人非常頭疼的事情——切換輸入法&#xff0c;特別是對于那些勤于寫注釋的朋友&#xff0c;簡直就是噩夢&#xff0c;正所謂懶人推動世界發展&#xff0c;這不&#xff0c;今天就向大家推薦一款好用的vscode插件&#…

ES6 Class(類) 總結(九)

ES6 中的 class 是一種面向對象編程的語法糖&#xff0c;提供了一種簡潔的方式來定義對象的結構和行為。 JavaScript 語言中&#xff0c;生成實例對象的傳統方法是通過構造函數。下面是一個例子。 function Point(x, y) {this.x x;this.y y; } Point.prototype.toString fu…

使用定時器消除抖動

問題&#xff1a;定時器中斷和按鍵中斷屬于什么操作模式&#xff0c;輪詢嗎&#xff1f; 具體怎么實現 定時器中斷 &#xff08;判斷&#xff09; 時間參數 按鍵中斷&#xff08;修改&#xff09; 中斷 向量表.s文件 DCD SysTick_Handler …

如何理解跨界營銷?詳解跨界營銷的主要類型和方法!

跨界營銷是一種創新的營銷策略&#xff0c;它巧妙地捕捉不同行業、產品和消費者偏好之間的共通點和潛在聯系。這種策略將看似不相關的元素相互融合&#xff0c;相互影響&#xff0c;創造出一種全新的生活方式和審美觀念&#xff0c;以此吸引目標消費者群體的注意和青睞。 通過…

Oracle左連接過濾條件注意事項

1、left join 結果集行數與主表查詢結果集行數一致 2、主表與輔表多關聯條件要括起來 3、對于輔表的過濾條件寫在on后面是先對輔表過濾后再與主表關聯&#xff0c;寫在where后面是對主表與輔表關聯后的結果集再進行過濾 4、對于主表的過濾條件寫在on后面不生效&#xff0c;只能…

LiveNVR監控流媒體Onvif/RTSP用戶手冊-用戶管理:編輯、添加用戶、關聯通道、重置密碼、刪除、過濾搜索

LiveNVR監控流媒體Onvif/RTSP用戶手冊-用戶管理:編輯、添加用戶、關聯通道、重置密碼、刪除、過濾搜索 1、用戶管理1.1、添加用戶1.2、關聯通道1.3、重置密碼1.4、編輯1.5、刪除1.6、過濾搜索 2、RTSP/HLS/FLV/RTMP拉流Onvif流媒體服務 1、用戶管理 1.1、添加用戶 點擊用戶管理…

學習網絡的第一步:全面解析OSI與TCP/IP模型

我是小米,一個喜歡分享技術的29歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術干貨! Hello,大家好!我是你們的好朋友小米。今天我們來聊一聊網絡基礎知識中的重量級選手——OSI模型和TCP/IP模型!網絡的世界就像一個巨大的迷宮,而這兩個…

Docker 鏡像構建報 exec xxx.sh: no such file or directory

問題記錄 場景&#xff1a; 處于對nacos docker 部署最新版本的探究&#xff0c;但是nacos/nacos-server鏡像拉取不到最新版本&#xff0c;官網也是給出自己構建鏡像的方案。 具體步驟很簡單&#xff0c;先clone項目&#xff0c;然后簽出你要的nacos版本&#xff0c;通過docke…