Java 8 引入了 Lambda 表达式与 Stream API,这不仅大幅减少了冗余代码,也让 Java 代码更简洁、函数式、更具表达力。对于刚接触 Java 8 的开发者来说,这两个新特性看起来有点“陌生”,但只要掌握核心语法和典型用法,就能迅速提升编码效率。
这篇文章是一次“再练”与复盘,也适合第一次接触 Java 8 的同学。从最基础的概念、语法规则、常见场景、到实战案例,我们都会一一展开。
在 Java 8 之前,Java 是一门“面向对象到极致”的语言。如果你想对一个集合执行一系列操作,比如筛选、排序、映射等,往往需要写很多 for 循环和匿名内部类,代码既冗长又不易维护。
Java 8 带来了两个“划时代”的工具:
这篇文章将手把手带你入门 Lambda 和 Stream,从“能看懂”到“能上手”,逐步进阶!
Lambda 是一种匿名函数(没有名字的函数),其主要作用是将行为(代码)作为参数进行传递。
它的基本语法如下:
(parameters) -> expression
或者
(parameters) -> { statements }
完整形式 | 简化形式 | 说明 |
---|---|---|
(String s) -> System.out.println(s) | s -> System.out.println(s) | 参数类型可推导,省略类型 |
(a, b) -> { return a + b; } | (a, b) -> a + b | 单行返回可省略 return 和大括号 |
// 传统方式
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello from Runnable!");
}
};
// Lambda 写法
Runnable r2 = () -> System.out.println("Hello from Lambda!");
List<String> list = Arrays.asList("banana", "apple", "pear");
// 传统方式
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
// Lambda 简写
Collections.sort(list, (a, b) -> a.compareTo(b));
只包含一个抽象方法的接口,就叫做函数式接口。常见的如:
Runnable
Comparator
Callable
Function
Predicate
Consumer
@FunctionalInterface
public interface MyFunction {
void execute();
}
Stream 是 Java 8 中用于处理集合的全新抽象概念。通过 声明式链式操作,可以实现集合的筛选、映射、排序、聚合等操作。
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream1 = list.stream(); // 普通 stream
Stream<String> stream2 = list.parallelStream(); // 并行 stream
Stream<Integer> stream3 = Stream.of(1, 2, 3, 4);
Stream<Double> stream4 = Stream.generate(Math::random).limit(5);
操作方法 | 说明 |
---|---|
filter | 过滤符合条件的元素 |
map | 对每个元素进行转换 |
sorted | 排序操作 |
distinct | 去重 |
limit(n) / skip(n) | 限制/跳过前n个元素 |
List<String> names = Arrays.asList("Tom", "Jerry", "Tim", "John");
List<String> filtered = names.stream()
.filter(name -> name.startsWith("T"))
.collect(Collectors.toList());
操作方法 | 说明 |
---|---|
forEach | 遍历每个元素 |
collect | 收集成集合 |
count | 统计数量 |
reduce | 规约成一个结果 |
List<String> upper = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
class User {
String name;
int age;
}
List<User> users = Arrays.asList(
new User("Tom", 28),
new User("Jerry", 22),
new User("Lucy", 30)
);
List<String> result = users.stream()
.filter(u -> u.getAge() > 25)
.sorted(Comparator.comparing(User::getAge))
.map(User::getName)
.collect(Collectors.toList());
输出:
[Tom, Lucy]
需求 | 示例 |
---|---|
求最大值 | list.stream().max(Integer::compareTo).get() |
去除 null 值 | list.stream().filter(Objects::nonNull) |
统计词频 | stream.collect(Collectors.groupingBy(w -> w, Collectors.counting())) |
转 Map | .collect(Collectors.toMap(User::getId, User::getName)) |
Lambda 更像是一种“写法革新”,消除了匿名内部类的冗余;Stream 则更像是“处理思想”的变化,引导我们用声明式、函数式的方式处理集合。