Lambda 表达式之所以能在 Java 中发挥强大作用,离不开函数式接口的支持。函数式接口是只有一个抽象方法的接口,它为 Lambda
表达式提供了目标类型,是 Java 函数式编程的基石。

函数式接口的本质
函数式接口的核心特征是:只有一个抽象方法。这种设计使得 Lambda 表达式能够简洁地实现该接口,而不需要显式地创建实现类。

java
// 传统实现方式
Runnable traditional = new Runnable() {
@Override
public void run() {
System.out.println(“传统实现”);
}
};

// Lambda实现方式
Runnable lambda = () -> System.out.println(“Lambda实现”);

// 编译后两者本质相同,但Lambda更简洁
@FunctionalInterface 注解
@FunctionalInterface 注解用于标识一个接口是函数式接口。它不是强制性的,但提供了重要的编译时检查:

java
@FunctionalInterface
interface StringProcessor {
String process(String input);

// 允许:默认方法
default void log(String message) {
    System.out.println("日志: " + message);
}

// 允许:静态方法
static StringProcessor createDefault() {
    return input -> "处理: " + input;
}

// 允许:Object类的方法(不算抽象方法)
@Override
boolean equals(Object obj);

}

// 编译错误:多个抽象方法
// @FunctionalInterface
// interface InvalidFunctional {
// void method1();
// void method2(); // 错误:只能有一个抽象方法
// }
Java 8 内置函数式接口
Java 8 在 java.util.function 包中提供了一系列常用的函数式接口:

  1. Consumer:消费型接口
    接受一个参数,执行操作,不返回结果。

java
public class ConsumerDemo {
public static void main(String[] args) {
// 基本使用
Consumer printer = System.out::println;
printer.accept(“Hello Consumer”);

    // 链式操作
    Consumer<String> toUpper = s -> System.out.println(s.toUpperCase());
    Consumer<String> addPrefix = s -> System.out.println(">>> " + s);
    
    // andThen: 顺序执行
    Consumer<String> combined = toUpper.andThen(addPrefix);
    combined.accept("chain");
    
    // 实际应用:集合遍历
    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    names.forEach(printer);
    
    // 复杂消费:更新对象状态
    Consumer<User> birthdayGreeting = user -> {
        user.setAge(user.getAge() + 1);
        System.out.println(user.getName() + " 生日快乐!现在 " + user.getAge() + " 岁");
    };
    
    User alice = new User("Alice", 25);
    birthdayGreeting.accept(alice);
}

static class User {
    String name;
    int age;
    
    User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    String getName() { return name; }
    int getAge() { return age; }
    void setAge(int age) { this.age = age; }
}

}

  1. Supplier:供给型接口
    不接受参数,返回一个结果。

java
public class SupplierDemo {
public static void main(String[] args) {
// 基本使用
Supplier randomSupplier = Math::random;
System.out.println(“随机数: “ + randomSupplier.get());

    // 缓存示例
    Supplier<ExpensiveObject> cachedSupplier = new Supplier<>() {
        private ExpensiveObject cached;
        
        @Override
        public ExpensiveObject get() {
            if (cached == null) {
                System.out.println("创建新对象...");
                cached = new ExpensiveObject();
            }
            return cached;
        }
    };
    
    // 首次调用创建对象
    cachedSupplier.get();
    // 后续调用使用缓存
    cachedSupplier.get();
    
    // 配置提供者模式
    Supplier<Config> configSupplier = () -> {
        Config config = new Config();
        config.loadFromFile("config.properties");
        return config;
    };
    
    // 延迟初始化
    LazyService service = new LazyService(configSupplier);
}

static class ExpensiveObject {
    ExpensiveObject() {
        System.out.println("ExpensiveObject 构造中...");
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
    }
}

static class Config {
    void loadFromFile(String path) {
        System.out.println("加载配置: " + path);
    }
}

static class LazyService {
    private Supplier<Config> configSupplier;
    private Config config;
    
    LazyService(Supplier<Config> configSupplier) {
        this.configSupplier = configSupplier;
    }
    
    void doWork() {
        if (config == null) {
            config = configSupplier.get();  // 延迟初始化
        }
        // 使用配置
    }
}

}

  1. Predicate:断言型接口
    接受一个参数,返回 boolean 值。

java
public class PredicateDemo {
public static void main(String[] args) {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

    // 基本断言
    Predicate<Integer> isEven = n -> n % 2 == 0;
    Predicate<Integer> isGreaterThan5 = n -> n > 5;
    
    // 组合断言
    Predicate<Integer> isEvenAndGreaterThan5 = isEven.and(isGreaterThan5);
    Predicate<Integer> isOdd = isEven.negate();
    Predicate<Integer> isLessThanOrEqualTo5 = isGreaterThan5.negate();
    
    System.out.println("偶数且大于5:");
    numbers.stream()
            .filter(isEvenAndGreaterThan5)
            .forEach(System.out::println);
    
    // 复杂业务验证
    List<User> users = Arrays.asList(
            new User("Alice", 25, "alice@email.com"),
            new User("Bob", 17, "bob.email.com"),  // 无效邮箱
            new User("Charlie", 30, null),         // 空邮箱
            new User("Diana", 22, "diana@email.com")
    );
    
    Predicate<User> isAdult = user -> user.age >= 18;
    Predicate<User> hasValidEmail = user -> 
            user.email != null && user.email.contains("@");
    
    System.out.println("\n成年且邮箱有效的用户:");
    users.stream()
            .filter(isAdult.and(hasValidEmail))
            .map(User::getName)
            .forEach(System.out::println);
    
    // 动态构建复杂谓词
    SearchCriteria criteria = new SearchCriteria();
    criteria.minAge = 20;
    criteria.maxAge = 35;
    criteria.emailRequired = true;
    
    Predicate<User> dynamicPredicate = buildUserPredicate(criteria);
    
    System.out.println("\n符合搜索条件的用户:");
    users.stream()
            .filter(dynamicPredicate)
            .forEach(System.out::println);
}

static Predicate<User> buildUserPredicate(SearchCriteria criteria) {
    Predicate<User> predicate = user -> true;  // 初始条件
    
    if (criteria.minAge != null) {
        predicate = predicate.and(user -> user.age >= criteria.minAge);
    }
    if (criteria.maxAge != null) {
        predicate = predicate.and(user -> user.age <= criteria.maxAge);
    }
    if (criteria.emailRequired != null && criteria.emailRequired) {
        predicate = predicate.and(user -> 
                user.email != null && user.email.contains("@"));
    }
    
    return predicate;
}

static class User {
    String name;
    int age;
    String email;
    
    User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }
    
    String getName() { return name; }
    
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

static class SearchCriteria {
    Integer minAge;
    Integer maxAge;
    Boolean emailRequired;
}

}

  1. Function<T, R>:函数型接口
    接受一个参数,返回一个结果。

java
public class FunctionDemo {
public static void main(String[] args) {
// 基本转换
Function<String, Integer> lengthFunction = String::length;
System.out.println(“字符串长度: “ + lengthFunction.apply(“Hello”));

    // 链式转换
    Function<String, String> toUpper = String::toUpperCase;
    Function<String, String> addExclamation = s -> s + "!";
    
    Function<String, String> pipeline = toUpper.andThen(addExclamation);
    System.out.println("处理结果: " + pipeline.apply("hello"));
    
    // 数学运算链
    Function<Integer, Integer> times2 = x -> x * 2;
    Function<Integer, Integer> squared = x -> x * x;
    
    System.out.println("(3 * 2)^2 = " + times2.andThen(squared).apply(3));
    System.out.println("3^2 * 2 = " + times2.compose(squared).apply(3));
    
    // 实际应用:数据转换管道
    List<Person> people = Arrays.asList(
            new Person("Alice", "Johnson", 25),
            new Person("Bob", "Smith", 30),
            new Person("Charlie", "Brown", 35)
    );
    
    // 转换管道:Person -> 全名 -> 大写
    Function<Person, String> fullName = 
            p -> p.getFirstName() + " " + p.getLastName();
    Function<String, String> upperCase = String::toUpperCase;
    
    System.out.println("\n人员全名(大写):");
    people.stream()
            .map(fullName.andThen(upperCase))
            .forEach(System.out::println);
    
    // 复杂转换:对象到DTO
    Function<Person, PersonDTO> toDTO = person -> {
        PersonDTO dto = new PersonDTO();
        dto.name = person.getFirstName() + " " + person.getLastName();
        dto.ageGroup = person.getAge() < 30 ? "青年" : "中年";
        return dto;
    };
    
    System.out.println("\n转换为DTO:");
    people.stream()
            .map(toDTO)
            .forEach(dto -> System.out.println(dto.name + " - " + dto.ageGroup));
}

static class Person {
    String firstName;
    String lastName;
    int age;
    
    Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    
    String getFirstName() { return firstName; }
    String getLastName() { return lastName; }
    int getAge() { return age; }
}

static class PersonDTO {
    String name;
    String ageGroup;
}

}

  1. 其他常用函数式接口
    java
    public class OtherFunctionalInterfaces {
    public static void main(String[] args) {
    // BiFunction: 接受两个参数,返回一个结果
    BiFunction<Integer, Integer, Integer> adder = Integer::sum;
    System.out.println(“10 + 20 = “ + adder.apply(10, 20));

     // UnaryOperator: 接受一个参数,返回同类型结果(Function的特例)
     UnaryOperator<String> repeater = s -> s + s;
     System.out.println("重复: " + repeater.apply("AB"));
     
     // BinaryOperator: 接受两个同类型参数,返回同类型结果
     BinaryOperator<Integer> multiplier = (a, b) -> a * b;
     System.out.println("10 * 20 = " + multiplier.apply(10, 20));
     
     // BiPredicate: 接受两个参数的断言
     BiPredicate<String, String> startsWith = String::startsWith;
     System.out.println("是否以开头: " + startsWith.test("hello", "he"));
     
     // BiConsumer: 接受两个参数的消费者
     BiConsumer<String, Integer> printer = (name, age) -> 
             System.out.println(name + " is " + age + " years old");
     printer.accept("Alice", 25);
     
     // 特殊化的函数式接口(避免装箱)
     IntFunction<String> intToString = String::valueOf;
     ToIntFunction<String> stringLength = String::length;
     IntConsumer printInt = System.out::println;
     
     System.out.println("整数转字符串: " + intToString.apply(42));
     System.out.println("字符串长度: " + stringLength.applyAsInt("Hello"));
     printInt.accept(100);
    

    }
    }
    自定义函数式接口
    虽然 Java 8 提供了丰富的内置函数式接口,但有时我们需要自定义:

java
public class CustomFunctionalInterface {
public static void main(String[] args) {
// 自定义三元运算接口
TriFunction<Integer, Integer, Integer, Integer> sumAll =
(a, b, c) -> a + b + c;
System.out.println(“三元和: “ + sumAll.apply(10, 20, 30));

    // 自定义带异常的函数式接口
    ThrowingFunction<String, Integer, NumberFormatException> parser = 
            Integer::parseInt;
    
    try {
        int result = parser.apply("123");
        System.out.println("解析结果: " + result);
    } catch (NumberFormatException e) {
        System.out.println("解析失败");
    }
    
    // 领域特定函数式接口
    Validator<String> emailValidator = email -> 
            email != null && email.contains("@") && email.contains(".");
    
    System.out.println("邮箱验证:");
    System.out.println("alice@example.com: " + emailValidator.validate("alice@example.com"));
    System.out.println("invalid-email: " + emailValidator.validate("invalid-email"));
}

// 自定义三元函数式接口
@FunctionalInterface
interface TriFunction<T, U, V, R> {
    R apply(T t, U u, V v);
    
    default <W> TriFunction<T, U, V, W> andThen(Function<? super R, ? extends W> after) {
        Objects.requireNonNull(after);
        return (T t, U u, V v) -> after.apply(apply(t, u, v));
    }
}

// 自定义带异常抛出的函数式接口
@FunctionalInterface
interface ThrowingFunction<T, R, E extends Exception> {
    R apply(T t) throws E;
}

// 领域特定:验证器接口
@FunctionalInterface
interface Validator<T> {
    boolean validate(T value);
    
    default Validator<T> and(Validator<T> other) {
        return value -> this.validate(value) && other.validate(value);
    }
    
    default Validator<T> or(Validator<T> other) {
        return value -> this.validate(value) || other.validate(value);
    }
    
    static <T> Validator<T> alwaysValid() {
        return value -> true;
    }
}

}
函数式接口的设计模式应用
函数式接口让传统设计模式变得更加简洁:

java
public class FunctionalDesignPatterns {
public static void main(String[] args) {
// 策略模式
System.out.println(“=== 策略模式 ===”);
PaymentProcessor processor = new PaymentProcessor();

    // 传统方式需要创建策略类
    // Lambda方式:直接传递行为
    processor.processPayment(100.0, amount -> {
        System.out.println("信用卡支付: $" + amount);
        return true;
    });
    
    processor.processPayment(50.0, amount -> {
        System.out.println("PayPal支付: $" + amount);
        return true;
    });
    
    // 模板方法模式
    System.out.println("\n=== 模板方法模式 ===");
    DataImporter csvImporter = new DataImporter(
            "data.csv",
            line -> line.split(","),          // CSV解析策略
            fields -> new DataRecord(fields)  // 记录创建策略
    );
    
    csvImporter.importData();
    
    // 观察者模式
    System.out.println("\n=== 观察者模式 ===");
    EventBus bus = new EventBus();
    
    // 注册观察者(使用Lambda)
    bus.subscribe("user.login", event -> 
            System.out.println("记录登录日志: " + event));
    
    bus.subscribe("user.login", event -> 
            System.out.println("发送登录通知: " + event));
    
    bus.subscribe("order.created", event -> 
            System.out.println("处理新订单: " + event));
    
    // 发布事件
    bus.publish("user.login", "用户Alice登录");
    bus.publish("order.created", "订单#12345创建");
}

// 策略模式实现
static class PaymentProcessor {
    interface PaymentStrategy {
        boolean pay(double amount);
    }
    
    void processPayment(double amount, PaymentStrategy strategy) {
        System.out.println("开始处理支付...");
        boolean success = strategy.pay(amount);
        System.out.println("支付结果: " + (success ? "成功" : "失败"));
    }
}

// 模板方法模式实现
static class DataImporter {
    private String filePath;
    private Function<String, String[]> parser;
    private Function<String[], DataRecord> creator;
    
    DataImporter(String filePath, 
                Function<String, String[]> parser,
                Function<String[], DataRecord> creator) {
        this.filePath = filePath;
        this.parser = parser;
        this.creator = creator;
    }
    
    void importData() {
        // 模板方法:固定流程
        openFile(filePath);
        processLines();
        closeFile();
    }
    
    private void openFile(String path) {
        System.out.println("打开文件: " + path);
    }
    
    private void processLines() {
        // 模拟读取行
        String[] lines = {"Alice,25,alice@email.com", "Bob,30,bob@email.com"};
        
        for (String line : lines) {
            String[] fields = parser.apply(line);      // 可变部分
            DataRecord record = creator.apply(fields); // 可变部分
            System.out.println("导入记录: " + record);
        }
    }
    
    private void closeFile() {
        System.out.println("关闭文件");
    }
}

static class DataRecord {
    String[] fields;
    DataRecord(String[] fields) { this.fields = fields; }
    
    @Override
    public String toString() {
        return String.join(" | ", fields);
    }
}

// 观察者模式实现
static class EventBus {
    private Map<String, List<Consumer<String>>> subscribers = new HashMap<>();
    
    void subscribe(String eventType, Consumer<String> handler) {
        subscribers.computeIfAbsent(eventType, k -> new ArrayList<>())
                  .add(handler);
    }
    
    void publish(String eventType, String eventData) {
        List<Consumer<String>> handlers = subscribers.get(eventType);
        if (handlers != null) {
            handlers.forEach(handler -> handler.accept(eventData));
        }
    }
}

}
函数式接口的性能考量
java
public class FunctionalPerformance {
public static void main(String[] args) {
int iterations = 1000000;

    // 比较不同实现方式的性能
    System.out.println("=== 性能比较 ===");
    
    // 1. 传统匿名类
    long start = System.nanoTime();
    for (int i = 0; i < iterations; i++) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                // 空操作
            }
        };
        r.run();
    }
    long anonymousTime = System.nanoTime() - start;
    
    // 2. Lambda表达式
    start = System.nanoTime();
    for (int i = 0; i < iterations; i++) {
        Runnable r = () -> {};
        r.run();
    }
    long lambdaTime = System.nanoTime() - start;
    
    // 3. 方法引用
    start = System.nanoTime();
    for (int i = 0; i < iterations; i++) {
        Runnable r = FunctionalPerformance::doNothing;
        r.run();
    }
    long methodRefTime = System.nanoTime() - start;
    
    System.out.printf("匿名类:  %10d ns%n", anonymousTime);
    System.out.printf("Lambda:  %10d ns%n", lambdaTime);
    System.out.printf("方法引用:%10d ns%n", methodRefTime);
    
    // 函数组合的性能影响
    System.out.println("\n=== 函数组合性能 ===");
    
    Function<Integer, Integer> f1 = x -> x + 1;
    Function<Integer, Integer> f2 = x -> x * 2;
    Function<Integer, Integer> f3 = x -> x * x;
    
    // 分开调用
    start = System.nanoTime();
    for (int i = 0; i < iterations; i++) {
        int result = f3.apply(f2.apply(f1.apply(i)));
    }
    long separateTime = System.nanoTime() - start;
    
    // 组合后调用
    Function<Integer, Integer> combined = f1.andThen(f2).andThen(f3);
    start = System.nanoTime();
    for (int i = 0; i < iterations; i++) {
        int result = combined.apply(i);
    }
    long combinedTime = System.nanoTime() - start;
    
    System.out.printf("分开调用: %d ns%n", separateTime);
    System.out.printf("组合调用: %d ns%n", combinedTime);
}

static void doNothing() {
    // 空方法
}

}
最佳实践与常见陷阱
✅ 最佳实践:
优先使用内置接口:除非有特殊需求,否则使用标准库中的函数式接口

保持简洁:函数式接口的实现应该简短,复杂逻辑提取为方法

合理命名:自定义函数式接口时使用有意义的名称

使用@FunctionalInterface注解:即使只有一个抽象方法也加上,增加编译时检查

❌ 常见陷阱:
过度自定义:不要为每个场景都创建新的函数式接口

java
// 不好:不必要的自定义
@FunctionalInterface
interface StringTransformer {
String transform(String input);
}

// 好:使用标准接口
Function<String, String> transformer;
忽略异常处理:Lambda中抛出检查异常需要特殊处理

java
// 错误:Lambda中不能直接抛出检查异常
// Function<String, Integer> parser = Integer::parseInt;

// 正确:包装异常
Function<String, Integer> parser = s -> {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
throw new RuntimeException(e);
}
};
误用函数式接口:不要在所有地方都强制使用函数式接口

java
// 不好:过度使用
interface UserProcessor {
void process(User user);
}

// 有时传统接口设计更好
interface UserService {
void save(User user);
void delete(Long id);
User findById(Long id);
}
总结
函数式接口是 Java 8 函数式编程的核心构件,它们:

为Lambda提供目标类型:使得Lambda表达式能够简洁地实现接口

促进代码复用:标准化的函数式接口可以在不同场景中重用

增强API设计:使API更加灵活,支持行为参数化

简化设计模式:让许多传统设计模式实现更加简洁

掌握函数式接口的关键在于理解其设计哲学:一个接口只定义一个抽象操作。通过合理使用内置和自定义的函数式接口,你可以编写出更加灵活、简洁和可维护的代码。

记住:函数式接口是工具,而不是目标。根据实际需求选择合适的设计,不要为了使用函数式接口而过度设计。当函数式接口能让代码更清晰、更简洁时,就大胆使用它;当传统设计更合适时,也不要犹豫选择传统方式。