首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 函數式編程(四):使用 Stream API 高效查找集合元素

     編輯:Java 相關知識

前言

在前幾篇文章中,我們已經熟悉了如何使用 Stream API 优雅地转换集合。然而,當我們需要「查找」符合條件的元素時,傳統的迴圈寫法不僅冗長,還容易出錯。本文將介紹 filter() 方法,展示如何用函數式風格輕鬆完成篩選操作,並探討如何避免 Lambda 表達式帶來的代碼冗餘問題。

傳統迴圈 vs. Stream filter()

傳統寫法:繁瑣且易出錯

假設我們要從名字列表中找出所有以「N」開頭的名字:

final List<String> startsWithN = new ArrayList<>();
for (String name : friends) {
    if (name.startsWith("N")) {
        startsWithN.add(name);
    }
}

這段代碼需要手動創建列表、迭代、判斷、添加,四步操作才能完成一個簡單的篩選任務。

函數式寫法:簡潔明瞭

使用 filter() 方法,同樣的邏輯只需一行鏈式調用:

final List<String> startsWithN =
    friends.stream()
           .filter(name -> name.startsWith("N"))
           .collect(Collectors.toList());

filter() 接受一個返回 boolean 的 Predicate,只保留滿足條件的元素,最終通過 collect() 收集為新列表。運行結果:

Found 2 names

filter() 與 map() 的關鍵差異

  • map():輸出集合大小與輸入一致,屬於一對一轉換。
  • filter():輸出集合大小介於 0 到輸入大小之間,屬於子集篩選。

Lambda 表達式的重用與 DRY 原則

雖然 Lambda 簡潔,但若在多處重複相同邏輯(如對不同列表都篩選「N」開頭),會導致代碼冗余,違反 DRY(Don't Repeat Yourself)原則。

問題示例

final long countFriendsStartN = friends.stream().filter(name -> name.startsWith("N")).count();
final long countEditorsStartN = editors.stream().filter(name -> name.startsWith("N")).count();
final long countComradesStartN = comrades.stream().filter(name -> name.startsWith("N")).count();

三處相同的 name -> name.startsWith("N") 違反了重用原則。

解決方案:將 Lambda 存入 Predicate 變量

filter() 參數類型是 java.util.function.Predicate<T>,我們可以顯式聲明並重用:

final Predicate<String> startsWithN = name -> name.startsWith("N");

final long countFriendsStartN = friends.stream().filter(startsWithN).count();
final long countEditorsStartN = editors.stream().filter(startsWithN).count();
final long countComradesStartN = comrades.stream().filter(startsWithN).count();

這樣邏輯只寫一次,後續直接引用變量,既消除冗余,又便於維護與性能優化。

總結

filter() 讓集合篩選變得聲明式且高效。配合 Predicate 變量重用,能進一步提升代碼質量。下一篇將探討如何用「詞法作用域」與「閉包」解決更複雜的參數化篩選需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved