20 個 Lambda+Stream 代碼示例,簡化開發
還在寫一堆循環和判斷來處理集合?Lambda 和 Stream 一行代碼搞定的事,不要再寫十幾行了!今天這篇文章,我整理了 20 個 Lambda+Stream 實戰案例,從基礎到進階,讓代碼量減少 50%,開發效率直接翻倍!

一、Lambda 表達式:告別冗余代碼
1. 替代匿名內部類,讓代碼更簡潔
以前寫線程 Runnable 要嵌套匿名內部類,代碼又長又亂:
// 傳統方式
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("線程執行了");
}
}).start();
// Lambda 方式(一行搞定)
new Thread(() -> System.out.println("線程執行了")).start();核心邏輯:Lambda 表達式用 ()->{} 代替了匿名內部類,當方法體只有一行時,大括號和 return 都可以省略。
2. 集合排序:告別復雜的 Comparator
對列表排序時,Lambda 能把比較邏輯壓縮成一行:
List<String> names = Arrays.asList("張三", "李四", "王五");
// 傳統排序(按長度)
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
// Lambda 排序
names.sort((a, b) -> a.length() - b.length());
// 更簡潔:用方法引用
names.sort(Comparator.comparingInt(String::length));3. 自定義函數式接口:靈活傳遞邏輯
定義一個簡單的函數式接口(只有一個抽象方法),用 Lambda 傳遞具體實現:
// 自定義函數式接口
@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}
// 使用 Lambda 實現加法和乘法
MathOperation addition = (a, b) -> a + b;
MathOperation multiplication = (a, b) -> a * b;
System.out.println(addition.operate(3, 5)); // 輸出 8
System.out.println(multiplication.operate(3, 5)); // 輸出 15二、Stream 流:讓集合操作飛起來
4. 遍歷集合:替代 for 循環
用 forEach 遍歷集合,代碼更緊湊,還能配合 Lambda 寫邏輯:
List<String> fruits = Arrays.asList("蘋果", "香蕉", "橙子");
// 傳統 for 循環
for (String fruit : fruits) {
System.out.println(fruit);
}
// Stream 遍歷
fruits.stream().forEach(fruit -> System.out.println(fruit));
// 方法引用更簡潔
fruits.forEach(System.out::println);5. 篩選元素:按條件過濾集合
從集合中篩選出符合條件的元素,比如找出所有偶數:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
// 篩選出偶數
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0) // 過濾條件
.collect(Collectors.toList()); // 收集結果
System.out.println(evenNumbers); // 輸出 [2, 4, 6]6. 映射轉換:將一種類型轉為另一種
把集合中的元素轉換成新的類型,比如提取用戶列表中的姓名:
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 25)
);
// 提取所有用戶名
List<String> usernames = users.stream()
.map(User::getName) // 調用 User 的 getName 方法
.collect(Collectors.toList());
System.out.println(usernames); // 輸出 [張三, 李四]三、Stream 進階操作:復雜邏輯簡單化
7. 排序:按字段對集合排序
對用戶列表按年齡排序,無需手動實現 Comparator:
List<User> users = Arrays.asList(
new User("張三", 25),
new User("李四", 20),
new User("王五", 30)
);
// 按年齡升序排序
List<User> sortedByAge = users.stream()
.sorted(Comparator.comparingInt(User::getAge))
.collect(Collectors.toList());
// 按年齡降序排序(加 reversed())
List<User> sortedByAgeDesc = users.stream()
.sorted(Comparator.comparingInt(User::getAge).reversed())
.collect(Collectors.toList());8. 去重:快速去除集合中的重復元素
用 distinct() 方法一鍵去重,比手動遍歷判斷高效 10 倍:
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(distinctNumbers); // 輸出 [1, 2, 3]9. 限制和跳過:取前 N 個或跳過前 N 個元素
分頁查詢時特別有用,比如取列表中的前 2 個元素:
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 25),
new User("王五", 30)
);
// 取前 2 個元素
List<User> top2 = users.stream()
.limit(2)
.collect(Collectors.toList());
// 跳過前 1 個,取剩下的
List<User> skip1 = users.stream()
.skip(1)
.collect(Collectors.toList());四、聚合操作:統計分析一鍵搞定
10. 求和:計算集合中數值的總和
計算訂單金額總和,不用再循環累加:
List<Order> orders = Arrays.asList(
new Order(100.0),
new Order(200.0),
new Order(300.0)
);
// 計算總金額
double total = orders.stream()
.mapToDouble(Order::getAmount) // 轉為 DoubleStream
.sum(); // 求和
System.out.println(total); // 輸出 600.011. 求最大值 / 最小值:快速找到集合中的極值
找出最大年齡的用戶:
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 25),
new User("王五", 30)
);
// 求最大年齡
OptionalInt maxAge = users.stream()
.mapToInt(User::getAge)
.max();
// 求最小年齡
OptionalInt minAge = users.stream()
.mapToInt(User::getAge)
.min();
// 輸出結果(用 orElse 避免空指針)
System.out.println(maxAge.orElse(0)); // 輸出 3012. 計數:統計符合條件的元素數量
統計年齡大于 25 的用戶數量:
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 25),
new User("王五", 30)
);
long count = users.stream()
.filter(user -> user.getAge() > 25)
.count();
System.out.println(count); // 輸出 1五、集合轉換:List、Set、Map 互轉
13. List 轉 Set:自動去重
把 List 轉換成 Set,順便去重:
List<String> list = Arrays.asList("a", "b", "a", "c");
Set<String> set = list.stream()
.collect(Collectors.toSet());
System.out.println(set); // 輸出 [a, b, c]14. List 轉 Map:用字段作為 key 或 value
將用戶列表轉換成 Map,key 為用戶名,value 為用戶對象:
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 25)
);
// 轉為 Map:key=姓名,value=用戶對象
Map<String, User> userMap = users.stream()
.collect(Collectors.toMap(
User::getName, // key 生成器
Function.identity() // value 生成器(用自身)
));坑點提醒:如果 key 有重復,會拋出 IllegalStateException,可以用第三個參數處理沖突:
// 遇到重復 key 時,保留第一個
Map<String, User> userMap = users.stream()
.collect(Collectors.toMap(
User::getName,
Function.identity(),
(existing, replacement) -> existing // 沖突時取 existing
));六、復雜場景實戰:鏈式操作解決難題
15. 多條件篩選 + 排序 + 提取字段
需求:從訂單列表中篩選出金額大于 100、狀態為已支付的訂單,按金額降序排序,最后提取訂單號:
List<Order> orders = Arrays.asList(
new Order("001", 150.0, "已支付"),
new Order("002", 80.0, "已支付"),
new Order("003", 200.0, "未支付"),
new Order("004", 300.0, "已支付")
);
List<String> orderNos = orders.stream()
// 篩選:金額>100 且 狀態為已支付
.filter(o -> o.getAmount() > 100 && "已支付".equals(o.getStatus()))
// 按金額降序排序
.sorted(Comparator.comparingDouble(Order::getAmount).reversed())
// 提取訂單號
.map(Order::getOrderNo)
// 收集結果
.collect(Collectors.toList());
System.out.println(orderNos); // 輸出 [004, 001]16. 批量處理:對集合中元素統一操作
給所有用戶的年齡加 1:
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 25)
);
// 批量修改年齡(注意:需 User 類有 setAge 方法)
users.stream()
.forEach(user -> user.setAge(user.getAge() + 1));17. 分組:按字段對集合分組
按用戶所在城市分組:
List<User> users = Arrays.asList(
new User("張三", "北京"),
new User("李四", "上海"),
new User("王五", "北京")
);
// 按城市分組:key=城市,value=該城市的用戶列表
Map<String, List<User>> groupByCity = users.stream()
.collect(Collectors.groupingBy(User::getCity));
// 輸出分組結果
groupByCity.forEach((city, userList) -> {
System.out.println(city + ":" + userList.stream()
.map(User::getName)
.collect(Collectors.toList()));
});
// 輸出:
// 北京:[張三, 王五]
// 上海:[李四]七、Lambda 與 Optional:避免空指針異常
18. Optional 處理可能為 null 的值
以前判斷對象是否為 null 要寫多層嵌套,用 Optional 一行搞定:
// 傳統方式(多層判空)
String username = null;
if (user != null) {
Address address = user.getAddress();
if (address != null) {
username = address.getCity();
}
}
// Optional 方式
String city = Optional.ofNullable(user)
.map(User::getAddress) // 調用 getAddress(),若為 null 則停止
.map(Address::getCity)
.orElse("未知城市"); // 若最終為 null,返回默認值19. 集合中查找第一個符合條件的元素
用 findFirst() 快速找到第一個滿足條件的元素,避免遍歷整個集合:
List<User> users = Arrays.asList(
new User("張三", 20),
new User("李四", 25),
new User("王五", 30)
);
// 查找第一個年齡大于 22 的用戶
Optional<User> user = users.stream()
.filter(u -> u.getAge() > 22)
.findFirst();
// 存在則輸出姓名
user.ifPresent(u -> System.out.println(u.getName())); // 輸出 李四20. 并行流:利用多核 CPU 加速處理
數據量超大時,用 parallelStream() 開啟并行處理,自動利用多個線程加速:
// 處理 100 萬條數據(并行流)
List<Long> numbers = new ArrayList<>();
for (long i = 0; i < 1000000; i++) {
numbers.add(i);
}
// 并行計算總和(比普通 stream 快幾倍)
long sum = numbers.parallelStream()
.filter(n -> n % 2 == 0) // 篩選偶數
.mapToLong(n -> n)
.sum();注意:并行流適合無狀態、線程安全的操作,否則可能出現線程安全問題。
為什么 Lambda+Stream 能讓開發效率翻倍?
傳統集合操作需要寫大量循環、判斷和臨時變量,代碼冗長且可讀性差。而 Lambda+Stream 用鏈式調用和函數式編程的思想,把復雜邏輯壓縮成幾行代碼,帶來三大好處:
- 代碼量減少 50%:一行流操作頂十行循環
- 可讀性提升:鏈式操作像自然語言一樣直觀
- 并行處理簡單:一行 parallelStream() 就能利用多核 CPU
學會這些用法,原來要寫循環的,一行代碼就解決問題了,效率就是這么提升的!
























