20 個(gè) Lambda+Stream 代碼示例,簡(jiǎn)化開發(fā)
還在寫一堆循環(huán)和判斷來(lái)處理集合?Lambda 和 Stream 一行代碼搞定的事,不要再寫十幾行了!今天這篇文章,我整理了 20 個(gè) Lambda+Stream 實(shí)戰(zhàn)案例,從基礎(chǔ)到進(jìn)階,讓代碼量減少 50%,開發(fā)效率直接翻倍!

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
























