1.Lambda表达式

Lambda 表达式是一种匿名函数(没有名字的函数),可以作为方法参数传递,用于简化函数式接口(Functional Interface)的实现。简单来说,要用Lambda表达式,前提是必有函数式接口。

 函数式接口:有且仅有一个抽象方法的接口(可用 @FunctionalInterface 注解标注)

语法格式如下:

(parameters) -> statements 参数 -> 业务代码  或者如下的格式,适用于多行

 (parameters) -> { statements; }

演示代码如下:

//传统匿名函数写法 Runnable是一个函数式接口
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
};

//Lambda表达式写法
Runnable r = () -> System.out.println("Hello");

应用场景如下:

1. 集合操作(配合 Stream API)

List<String> list = Arrays.asList("apple", "banana", "cherry");

// 过滤包含 "a" 的字符串并计数
long count = list.stream()
                 .filter(s -> s.contains("a"))
                 .count();

// 转大写并收集
List<String> upper = list.stream()
                         .map(String::toUpperCase)
                         .collect(Collectors.toList());

2. 线程任务

new Thread(() -> {
    System.out.println("Running in thread: " + Thread.currentThread().getName());
}).start();

3. 事件监听(GUI / 回调)

button.addActionListener(e -> System.out.println("Button clicked!"));

4. 自定义函数式接口

@FunctionalInterface
interface MathOperation {
    int operate(int a, int b);
}

MathOperation add = (a, b) -> a + b;
MathOperation multiply = (a, b) -> a * b;

优点:

代码简洁,可读性强,支持函数式编程

缺点:

不能修改外部局部变量,调试困难

四大核心内置函数式接口

接口 名称 抽象方法 作用 入参 返回值
Consumer 消费者 void accept(T t) 消费数据,只处理不返回 有 T 无返回值 void
Supplier 生产者 T get() 生产数据,无参返回对象 无参数 返回 T
Predicate 断言 / 判断 boolean test(T t) 条件判断,返回布尔 有 T boolean
Function 函数 / 转换器 R apply(T t) 类型转换,T 转 R 有 T 返回 R

2.方法引用

方法引用(Method Reference)是 Java 8 引入的一种简洁语法,用于直接引用已有方法,而无需编写完整的 Lambda 表达式,可以理解他是方法引用的简化版本。如果 Lambda 只是调用一个已存在的方法,那就直接使用方法引用更方便。

1. 静态方法引用

List<Integer> numbers = Arrays.asList(-3, -1, 2, 5);

// Lambda 写法
List<Integer> abs1 = numbers.stream()
    .map(x -> Math.abs(x))
    .collect(Collectors.toList());

// 方法引用(更简洁)
List<Integer> abs2 = numbers.stream()
    .map(Math::abs) // ← 直接引用 Math.abs()
    .collect(Collectors.toList());

2. 特定对象的实例方法

String prefix = "Hello ";

List<String> names = Arrays.asList("Alice", "Bob");

// Lambda:每个名字都拼接到 prefix 后
List<String> greetings1 = names.stream()
    .map(name -> prefix.concat(name))
    .collect(Collectors.toList());

// 方法引用:固定使用 prefix 对象的 concat 方法
List<String> greetings2 = names.stream()
    .map(prefix::concat) // ← prefix 是外部变量
    .collect(Collectors.toList());

3. 任意对象的实例方法

这是我们日常开发过程中用到最多的一种模式

List<String> words = Arrays.asList("apple", "Banana", "cherry");

// Lambda
List<String> upper1 = words.stream()
    .map(s -> s.toUpperCase())
    .collect(Collectors.toList());

// 方法引用
List<String> upper2 = words.stream()
    .map(String::toUpperCase) // ← 每个字符串自己调用 toUpperCase()
    .collect(Collectors.toList());

// 其他例子
orderList.stream().map(Order::getName)     // 每个 Order 调用 getName()
users.stream().filter(User::isActive)      // 每个 User 调用 isActive()

构造器方法引用再开发中引用很少,基本没怎么用过,这里不做多余阐述。

3.Stream流

Stream API 是 JDK 8 引入的革命性特性,它让 Java 首次具备了声明式、函数式处理集合数据的能力。

3.1Stream API 的核心优点 

表格

优点 说明

1. 声明式编程

你只描述“要什么”(filter、map、group),不写“怎么做”(for 循环、if 判断)
2. 链式调用 多个操作可流畅串联:list.stream().filter(...).map(...).collect(...)
3. 惰性求值(Lazy Evaluation) 中间操作(如 filter、map)不立即执行,直到终端操作(如 collect、count)触发
4. 并行处理简单 只需 .parallelStream() 或 .parallel(),自动利用多核 CPU(但需谨慎!)
5. 减少样板代码 替代大量 for + if + add 的模板代码
6. 类型安全 & 编译时检查 比传统循环更少出错(如索引越界)

3.2Stream 操作

  • 中间操作(懒加载,不执行):filter、map、sorted、distinct、limit
  • 终端操作(触发执行,关闭流):collect、forEach、count、max、min、anyMatch

3.2.1. 过滤(filter)

// 获取所有已支付的订单
List<Order> paidOrders = orders.stream()
    .filter(order -> "PAID".equals(order.getStatus()))
    .collect(Collectors.toList());

3.2 2. 映射转换(map / flatMap)

// 提取所有商品名称
List<String> productNames = products.stream()
    .map(Product::getName)
    .collect(Collectors.toList());

// 展平:每个用户有多个收货地址 → 所有地址列表
List<Address> allAddresses = users.stream()
    .flatMap(user -> user.getAddresses().stream())
    .collect(Collectors.toList());

3.3 3. 去重(distinct)

// 获取所有不重复的商品分类
List<String> categories = products.stream()
    .map(Product::getCategory)
    .distinct()
    .collect(Collectors.toList());

3.3.4. 排序(sorted)

// 按订单金额降序
List<Order> sortedOrders = orders.stream()
    .sorted(Comparator.comparing(Order::getAmount).reversed())
    .collect(Collectors.toList());

3.3.5. 聚合统计(count / sum / max / min / average)

// 订单总数、总金额、平均金额
long count = orders.stream().count();
double total = orders.stream().mapToDouble(Order::getAmount).sum();
OptionalDouble avg = orders.stream().mapToDouble(Order::getAmount).average();

3.3.6. 分组(groupingBy)

// 按店铺分组订单
Map<Long, List<Order>> ordersByShop = orders.stream()
    .collect(Collectors.groupingBy(Order::getShopId));

// 按状态分组 + 统计每组数量
Map<String, Long> statusCount = orders.stream()
    .collect(Collectors.groupingBy(Order::getStatus, Collectors.counting()));

3.3.7. 分区(partitioningBy)

// 将商品分为“库存充足”和“缺货”两类
Map<Boolean, List<Product>> stockPartition = products.stream()
    .collect(Collectors.partitioningBy(p -> p.getStock() > 0));

3.3.8. 转为其他集合类型

// 转 Set(自动去重)
Set<String> skuSet = products.stream()
    .map(Product::getSku)
    .collect(Collectors.toSet());

// 转 Map(key=ID, value=对象)
Map<Long, Product> productMap = products.stream()
    .collect(Collectors.toMap(Product::getId, Function.identity()));

3.3. 9. 处理数组

String[] arr = {"a", "b", "c"};
List<String> list = Arrays.stream(arr)
    .filter(s -> !s.equals("b"))
    .collect(Collectors.toList());

3.3.10. 查找(findAny / findFirst)

// 找一个 VIP 用户
Optional<User> vipUser = users.stream()
    .filter(User::isVip)
    .findAny(); // 并行流用 findAny 更高效

4.Optional

Optional<T> 是 Java 8 引入的一个容器类(wrapper class),用于显式表达“一个值可能存在,也可能不存在” 的语义。它的核心目标不是“替代 null”,而是让空值处理更安全、更清晰、更具声明性

常用方法如下:

创建 Optional

方法 说明
Optional.of(T value) 创建非空 Optional(value 不能为 null)
Optional.ofNullable(T value) 最常用! value 可为 null,自动转为 empty
Optional.empty() 创建空 Optional

判断是否存在值

方法 说明
boolean isPresent() 有值返回 true
void ifPresent(Consumer<T> action) 有值则执行操作(推荐替代 if 判断)

安全获取值

方法 说明
T orElse(T other) 有值返回值,否则返回默认值
T orElseGet(Supplier<T> supplier)  懒加载默认值(仅在需要时计算)
T orElseThrow(Supplier<X> exceptionSupplier) 为空时抛出自定义异常

我们先来看一下下面这段代码

public String getUserName(User user) {
    return user.getName().toUpperCase(); 
}

这个方法很明显的有以下问题:

  • user 可能为 null
  • user.getName() 可能返回 null
  • 调用方不知道是否可能为 null,容易出错

那让我们来看看这个Optional是怎么做的

public Optional<String> getUserName(User user) {
    return Optional.ofNullable(user)
        .map(User::getName)
        .map(String::toUpperCase);
}

//调用如下:
String name = getUserName(user).orElse("匿名用户");


// 仅当你 100% 确定 user 和 name 都不为 null
String name = getUserName(user).get(); // ⚠️ 如果为空会抛 NoSuchElementException!

4.1Optional 的 5 大场景

4.1.1:方法返回值可能为空


public Optional<Product> findProductByName(String name) {
    Product p = productDao.findByName(name);
    return Optional.ofNullable(p);
}

// 调用方必须处理“找不到”的情况
productService.findProductByName("iPhone")
    .ifPresent(p -> order.setPrice(p.getPrice()));

适用于:DAO 查询、缓存查找、配置读取等可能无结果的操作。


4.1.2:多层嵌套对象的安全访问

// 传统写法(啰嗦)
if (user != null) {
    Address addr = user.getAddress();
    if (addr != null) {
        String city = addr.getCity();
        if (city != null) {
            return city.toUpperCase();
        }
    }
}

// Optional 写法(清晰)
return Optional.ofNullable(user)
    .map(User::getAddress)
    .map(Address::getCity)
    .map(String::toUpperCase)
    .orElse("未知城市");

适用于:用户资料、订单地址、JSON 解析等深度嵌套结构


4.1.3:Stream 流中的终端操作

List<Order> orders = ...;

// findFirst(), max(), min(), reduce() 等返回 Optional
Optional<Order> firstOrder = orders.stream().findFirst();
Optional<Order> mostExpensive = orders.stream()
    .max(Comparator.comparing(Order::getMoney));

// 安全处理
mostExpensive.ifPresent(order -> sendVIPCoupon(order));

 这是 Optional 最自然的使用场景,无需额外包装。


4.1.4:提供默认值或抛异常(比 if-else 更函数式)

String name = Optional.ofNullable(inputName)
    .filter(n -> n.length() > 2)
    .orElse("匿名用户");

// 或抛异常
User user = Optional.ofNullable(findUser(id))
    .orElseThrow(() -> new UserNotFoundException("ID=" + id));

📌 比 if (x == null) x = default; 更简洁、可链式组合。


4.1.5:函数式编程中的“空安全”组合

// 将多个可能为空的操作组合起来
public Optional<Invoice> generateInvoice(Long orderId) {
    return findOrder(orderId)           // Optional<Order>
        .filter(Order::isValid)
        .flatMap(this::calculateTax)    // 返回 Optional<Invoice>
        .map(this::applyDiscount);
}

最后有一句话来形容就是:

如果这个方法可能返回 null,并且调用方需要显式处理‘没有结果’的情况,那就返回 Optional。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐