Lambda 与 Stream
Java 8 引入了 Lambda 表达式 和 Stream API,让代码更简洁、更声明式。
1. Lambda 基础
Lambda 是匿名函数,可以赋值给变量、作为参数传递。
(参数) -> 表达式
(参数) -> { 语句; return 值; }import java.util.*;
public class Main {
public static void main(String[] args) {
// Runnable(无参无返回值)
Runnable hello = () -> System.out.println("Hello Lambda");
hello.run();
// 接收一个参数
var square = (int x) -> x * x;
System.out.println("5² = " + square.apply(5)); // 这里用 apply 演示
}
@FunctionalInterface
interface IntFunc {
int apply(int x);
}
}ℹ️函数式接口
只有一个抽象方法的接口称为函数式接口(@FunctionalInterface),可以被 Lambda 替换:
Runnable:() -> voidSupplier<T>:() -> TConsumer<T>:(T) -> voidFunction<T, R>:(T) -> RPredicate<T>:(T) -> boolean
2. 方法引用
当 Lambda 只是调用一个已存在的方法时,可以用 :: 简写。
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<String> langs = List.of("Java", "Go", "Python", "Rust");
// 等价于 s -> System.out.println(s)
langs.forEach(System.out::println);
// 等价于 s -> s.toUpperCase()
var uppers = langs.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(uppers);
}
}3. Stream 流水线
Stream 操作分两类:
- 中间操作:filter、map、sorted(返回新 Stream)
- 终止操作:collect、forEach、count(触发实际计算)
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 找出偶数,平方,求和
int sum = nums.stream()
.filter(n -> n % 2 == 0) // 留下偶数
.map(n -> n * n) // 平方
.reduce(0, Integer::sum); // 累加
System.out.println("偶数平方和 = " + sum);
// 排序
List<String> sorted = Stream.of("banana", "apple", "cherry")
.sorted()
.collect(Collectors.toList());
System.out.println(sorted);
// 统计
long count = nums.stream().filter(n -> n > 5).count();
System.out.println("大于 5 的有 " + count + " 个");
}
}4. 收集器 Collectors
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
record Person(String name, int age) {}
List<Person> people = List.of(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Carol", 28),
new Person("Dave", 30)
);
// 按年龄分组
Map<Integer, List<Person>> byAge = people.stream()
.collect(Collectors.groupingBy(Person::age));
System.out.println("按年龄分组: " + byAge);
// 统计平均年龄
double avg = people.stream()
.collect(Collectors.averagingInt(Person::age));
System.out.printf("平均年龄: %.2f%n", avg);
// 拼接名字
String names = people.stream()
.map(Person::name)
.collect(Collectors.joining(", "));
System.out.println("名字: " + names);
}
}ℹ️record 关键字
Java 14+ 的 record 是不可变数据类的语法糖:自动生成构造器、getter、equals、hashCode、toString。
5. Optional 防 NPE
Optional<T> 是可能为 null 的容器,强迫调用者显式处理「无值」。
import java.util.*;
public class Main {
public static void main(String[] args) {
Optional<String> a = Optional.of("hello");
Optional<String> b = Optional.empty();
System.out.println(a.orElse("default")); // hello
System.out.println(b.orElse("default")); // default
a.ifPresent(s -> System.out.println("非空: " + s));
b.ifPresent(s -> System.out.println("不会执行"));
// 链式
String r = Optional.of(" Hi ")
.map(String::trim)
.map(String::toUpperCase)
.orElse("EMPTY");
System.out.println(r);
}
}6. 实战:学生成绩分析
import java.util.*;
import java.util.stream.*;
public class Main {
record Student(String name, int score) {}
public static void main(String[] args) {
List<Student> students = List.of(
new Student("Alice", 85),
new Student("Bob", 92),
new Student("Carol", 78),
new Student("Dave", 95),
new Student("Eve", 88)
);
// Top 3
var top3 = students.stream()
.sorted(Comparator.comparingInt(Student::score).reversed())
.limit(3)
.toList();
System.out.println("前三名:");
top3.forEach(s -> System.out.printf(" %s: %d%n", s.name(), s.score()));
// 通过/未通过
long pass = students.stream().filter(s -> s.score() >= 60).count();
long fail = students.size() - pass;
System.out.printf("通过 %d,未通过 %d%n", pass, fail);
// 平均分
double avg = students.stream().collect(Collectors.averagingInt(Student::score));
System.out.printf("平均分 %.2f%n", avg);
}
}🎯 综合练习
// 任务:用 Lambda 对字符串列表按长度降序排序
// 期望输入:["Java", "Go", "Python", "Rust"]
// 期望输出:[Python, Java, Rust, Go]
import java.util.*;
public class Main {
public static void main(String[] args) {
List<String> langs = new ArrayList<>(List.of("Java", "Go", "Python", "Rust"));
// 补全代码
System.out.println(langs);
}
}小结
- ✅ Lambda:
() -> 表达式单方法接口的简写 - ✅ 方法引用
Class::method进一步简化 - ✅ Stream 流水线:filter / map / reduce / collect
- ✅
Collectors.groupingBy / joining / averagingInt - ✅
Optional<T>防 NPE - ✅
record是不可变数据类的语法糖
🎉 Java 8 章完结!你已经掌握了 Java 核心语法与常用 API。
到这里 Python / Go / Java 三门语言的核心章节都已完成。继续打磨或自行扩展专题章节(如「Python 数据分析」「Go Web 服务」「Java Spring」)即可。