1. 传统写法(结构多,重点被淹没)
// 创建并启动一个线程new Thread(new Runnable() {// Runnable 接口只有一个方法 run@Overridepublicvoidrun() {// 真正有用的逻辑其实只有这一行 System.out.println("do work"); }}).start();
问题:
2. Lambda 写法(只保留有用信息)
// () 表示没有参数// -> 后面就是 run 方法的实现new Thread(() -> { System.out.println("do work");}).start();
如果只有一行逻辑:
// 单行 Lambda 可以省略大括号new Thread(() -> System.out.println("do work")).start();
二、Stream API:把 for 循环拆成“步骤”
1. 传统 for 循环(多件事混在一起)
List<String> names = new ArrayList<>();for (User user : users) {// 判断条件 if (user.getAge() > 18) {// 数据转换 names.add(user.getName()); }}
读这段代码时,你需要在脑子里“拆逻辑”。
2. Stream 写法(一步一行)
List<String> names = users.stream() // 1. 从集合创建数据流 .filter(user -> user.getAge() > 18) // 2. 只保留年龄大于 18 的用户 .map(User::getName) // 3. 把 User 转换成 name .collect(Collectors.toList()); // 4. 把结果收集成 List
每一行只做一件事,
逻辑顺序非常清晰。
3. 常见 Stream 实战代码
求和
int total = orders.stream() // 获取订单集合流 .mapToInt(Order::getAmount) // 把订单转换成金额 int .sum(); // 对所有金额求和
分组
Map<String, List<User>> groupMap = users.stream() // 用户集合 .collect( Collectors.groupingBy( User::getDept // 按部门分组 ) );
去重
List<String> list = data.stream() // 原始数据流 .distinct() // 去重(依赖 equals) .collect(Collectors.toList()); // 转成 List
三、Optional:让“可能为空”变得明显
1. 传统写法(容易漏判断)
User user = getUser();if(user != null) { System.out.println(user.getName());}
这种写法的问题在于:
null 判断容易被遗漏。
2. Optional 写法(强制你处理空值)
Optional<User> optionalUser = getUserOptional();// 如果有值,才执行 Lambda 里的逻辑optionalUser.ifPresent(user -> { System.out.println(user.getName());});
从变量名就能看出来:
这个值可能为空。
3. 提供默认值
// 如果 optional 里有值,直接返回// 如果没有值,返回 new User()User user = optionalUser.orElse(new User());
或者懒加载:
// 只有在 optional 为空时,才会执行 User::newUser user = optionalUser.orElseGet(User::new);
4. 不推荐的用法
// 如果 optional 为空,这里直接抛异常User user = optionalUser.get();
这种写法违背了 Optional 的设计初衷。
四、方法引用:给 Lambda 再减一层
1. 普通 Lambda
users.stream() .map(user -> user.getName()) // 从 User 中取 name .forEach(name -> System.out.println(name));
2. 方法引用写法
users.stream() .map(User::getName) // 等价于 user -> user.getName() .forEach(System.out::println); // 等价于 name -> System.out.println(name)
方法引用只是 Lambda 的简写形式。
3. 常见方法引用类型
User::getName // 类名::实例方法System.out::println // 对象::实例方法Math::abs // 类名::静态方法
五、在项目中的“安全使用原则”
这是我在项目里长期用下来的经验:
// 逻辑简单,使用 Streamusers.stream() .filter(...) .map(...) .collect(...);// 逻辑复杂,老老实实用 forfor (...) { ...}
规则只有一个:
代码是给人看的,不是给编译器看的。
写在最后
Lambda、Stream、Optional
并没有让 Java “更难”,
只是让你: