Skip to content

Lambda 与函数式编程

Java 8 引入的 Lambda 和函数式接口,彻底改变了 Java 的编程风格。理解其底层实现,能帮你写出更简洁高效的代码。

Lambda 底层原理

java
// Lambda 不是匿名内部类!
// 底层使用 invokedynamic 指令 + LambdaMetafactory 实现

// 这段代码:
Runnable r = () -> System.out.println("Hello");

// 编译后大致等价于:
// 1. 生成一个静态方法 lambda$main$0
// 2. 通过 invokedynamic 在运行时动态绑定

// 验证:Lambda 不会生成 $1 这样的内部类文件
// 但匿名内部类会生成 MyClass$1.class

函数式接口

java
// Java 8 内置的核心函数式接口
// 都在 java.util.function 包

// Function<T, R> — 接受 T,返回 R
Function<String, Integer> strLen = String::length;
Function<Integer, String> intToStr = Object::toString;
// 组合
Function<String, String> composed = strLen.andThen(intToStr);
// "hello" → 5 → "5"

// Predicate<T> — 接受 T,返回 boolean
Predicate<String> isLong = s -> s.length() > 5;
Predicate<String> startsWithA = s -> s.startsWith("A");
// 组合
Predicate<String> combined = isLong.and(startsWithA);
Predicate<String> either = isLong.or(startsWithA);
Predicate<String> notLong = isLong.negate();

// Consumer<T> — 接受 T,无返回值
Consumer<String> printer = System.out::println;
Consumer<String> logger = s -> log.info(s);
Consumer<String> both = printer.andThen(logger);

// Supplier<T> — 无参数,返回 T
Supplier<List<String>> listFactory = ArrayList::new;
Supplier<LocalDateTime> now = LocalDateTime::now;

// BiFunction<T, U, R> — 接受 T 和 U,返回 R
BiFunction<String, Integer, String> repeat = String::repeat;
// "ha".repeat(3) = "hahaha"

// UnaryOperator<T> — Function<T, T> 的特化
UnaryOperator<String> toUpper = String::toUpperCase;

// BinaryOperator<T> — BiFunction<T, T, T> 的特化
BinaryOperator<Integer> add = Integer::sum;
BinaryOperator<String> concat = String::concat;

方法引用

java
// 四种方法引用形式

// 1. 静态方法引用:ClassName::staticMethod
Function<String, Integer> parseInt = Integer::parseInt;
Comparator<String> comp = String::compareTo;

// 2. 实例方法引用(特定实例):instance::method
String prefix = "Hello, ";
Function<String, String> greet = prefix::concat;

// 3. 实例方法引用(任意实例):ClassName::instanceMethod
Function<String, String> toUpper = String::toUpperCase;
Predicate<String> isEmpty = String::isEmpty;

// 4. 构造器引用:ClassName::new
Supplier<ArrayList<String>> listSupplier = ArrayList::new;
Function<Integer, ArrayList<String>> listWithCapacity = ArrayList::new;
BiFunction<String, Integer, StringBuilder> sbFactory = StringBuilder::new;

自定义函数式接口

java
// @FunctionalInterface 确保只有一个抽象方法
@FunctionalInterface
public interface Transformer<T, R> {
    R transform(T input);

    // 可以有默认方法和静态方法
    default <V> Transformer<T, V> andThen(Transformer<R, V> after) {
        return input -> after.transform(this.transform(input));
    }

    static <T> Transformer<T, T> identity() {
        return t -> t;
    }
}

// 使用
Transformer<String, Integer> length = String::length;
Transformer<Integer, String> toStr = n -> "长度: " + n;
Transformer<String, String> combined = length.andThen(toStr);
System.out.println(combined.transform("hello"));  // 长度: 5

// 受检异常的函数式接口
@FunctionalInterface
public interface CheckedFunction<T, R> {
    R apply(T t) throws Exception;

    static <T, R> Function<T, R> wrap(CheckedFunction<T, R> fn) {
        return t -> {
            try {
                return fn.apply(t);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
}

// 使用
List<String> paths = List.of("file1.txt", "file2.txt");
List<String> contents = paths.stream()
    .map(CheckedFunction.wrap(Files::readString))  // 包装受检异常
    .collect(Collectors.toList());

函数式编程模式

柯里化(Currying)

java
// 将多参数函数转为单参数函数链
Function<Integer, Function<Integer, Integer>> curriedAdd =
    a -> b -> a + b;

Function<Integer, Integer> add5 = curriedAdd.apply(5);
System.out.println(add5.apply(3));   // 8
System.out.println(add5.apply(10));  // 15

// 实用场景:部分应用
Function<String, Function<String, String>> format =
    template -> value -> template.replace("{}", value);

Function<String, String> greetTemplate = format.apply("Hello, {}!");
System.out.println(greetTemplate.apply("Alice"));  // Hello, Alice!
System.out.println(greetTemplate.apply("Bob"));    // Hello, Bob!

函数组合

java
// 构建处理管道
Function<String, String> trim = String::trim;
Function<String, String> toUpper = String::toUpperCase;
Function<String, String> addPrefix = s -> "PREFIX_" + s;

Function<String, String> pipeline = trim
    .andThen(toUpper)
    .andThen(addPrefix);

System.out.println(pipeline.apply("  hello  "));
// PREFIX_HELLO

// 使用 Stream 构建动态管道
List<Function<String, String>> transforms = List.of(
    String::trim,
    String::toUpperCase,
    s -> s.replace(" ", "_")
);

Function<String, String> combined = transforms.stream()
    .reduce(Function.identity(), Function::andThen);

System.out.println(combined.apply("  hello world  "));
// HELLO_WORLD

现代 Java 特性

java
// Java 16+ Record — 不可变数据类
public record Point(double x, double y) {
    // 紧凑构造器(验证)
    public Point {
        if (x < 0 || y < 0) throw new IllegalArgumentException("坐标不能为负");
    }

    // 自定义方法
    public double distanceTo(Point other) {
        return Math.sqrt(Math.pow(x - other.x, 2) + Math.pow(y - other.y, 2));
    }
}

Point p = new Point(3, 4);
System.out.println(p.x());  // 3.0(自动生成访问器)
System.out.println(p);      // Point[x=3.0, y=4.0]

// Java 17+ Sealed Classes — 限制继承
public sealed interface Shape permits Circle, Rectangle, Triangle {
    double area();
}

public record Circle(double radius) implements Shape {
    public double area() { return Math.PI * radius * radius; }
}

public record Rectangle(double width, double height) implements Shape {
    public double area() { return width * height; }
}

// Java 21 Pattern Matching for switch
double area = switch (shape) {
    case Circle c -> Math.PI * c.radius() * c.radius();
    case Rectangle r -> r.width() * r.height();
    case Triangle t -> t.base() * t.height() / 2;
};

函数式编程建议

  • 优先使用不可变数据(recordList.of()Map.of()
  • Optional 替代 null 检查
  • 用 Stream API 替代命令式循环
  • 函数式接口让代码更可测试(传入 mock 函数)

系统学习 Java 生态,深入底层架构