Java函数式接口——渐进式学习

一、函数式接口的定义

函数式接口 (Functional Interface) 是Java 8引入的核心概念,它是指有且仅有一个抽象方法的接口(可包含默认方法和静态方法)。这种接口可以用Lambda表达式方法引用来实现,是函数式编程在Java中的基础。

// 标准定义
@FunctionalInterface  // 编译期检查,可选但推荐
public interface MyFunction {
    String apply(int x);  // 唯一的抽象方法

    // 允许默认方法
    default void print(String msg) {
        System.out.println(msg);
    }

    // 允许静态方法
    static void log(String msg) {
        System.out.println("[LOG] " + msg);
    }
}

二、渐进式学习——代码示例

2.1 阶段1:从匿名类到Lambda演化

public class EvolutionDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 【传统方式】匿名内部类
        names.forEach(new Consumer<String>() {
            @Override
            public void accept(String name) {
                System.out.println(name);
            }
        });

        // 【方式1】Lambda完整语法
        names.forEach((String name) -> {
            System.out.println(name);
        });

        // 【方式2】Lambda简化(参数类型推导)
        names.forEach((name) -> System.out.println(name));

        // 【方式3】Lambda最简(单参数可省括号)
        names.forEach(name -> System.out.println(name));

        // 【方式4】方法引用(终极简化)
        names.forEach(System.out::println);
    }
}

2.2 阶段2:Java内置的四大核心函数式接口精讲

1. Consumer<T> - 消费型接口

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

作用:接收一个参数,不返回结果
示例:

// 打印字符串
Consumer<String> printer = s -> System.out.println(s);
printer.accept("Hello, Consumer!");

// 消费列表元素
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println("Hello, " + name));

2. Supplier<T>- 供给型接口

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

作用:不接收参数,返回一个结果
示例:

// 生成随机数
Supplier<Double> randomSupplier = () -> Math.random();
System.out.println("Random: " + randomSupplier.get());

// 延迟初始化
Supplier<String> lazyString = () -> {
    System.out.println("Initializing...");
    return "Lazy Value";
};
System.out.println("Before get");
System.out.println(lazyString.get());

3. Function<T, R> - 函数型接口

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

作用:接收一个参数,返回一个结果
示例:

// 字符串转整数
Function<String, Integer> stringToInt = s -> Integer.parseInt(s);
int result = stringToInt.apply("123");
System.out.println("Result: " + result);

// 函数组合
Function<Integer, Integer> doubleIt = x -> x * 2;
Function<Integer, Integer> addOne = x -> x + 1;
Function<Integer, Integer> composed = doubleIt.andThen(addOne);
System.out.println("Composed: " + composed.apply(5)); // 输出: 11

4. Predicate<T> - 断言型接口

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

作用:接收一个参数,返回布尔值
示例:

// 判断字符串是否为空
Predicate<String> isEmpty = s -> s == null || s.isEmpty();
System.out.println("Is empty: " + isEmpty.test("")); // true

// 过滤列表
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
System.out.println("Even numbers: " + evenNumbers); // [2, 4, 6]

2.3 阶段3:自定义函数式接口实践

// 定义业务相关的函数式接口
@FunctionalInterface
interface OrderValidator {
    boolean validate(Order order);
    
    // 默认方法:组合验证
    default OrderValidator and(OrderValidator other) {
        return order -> this.validate(order) && other.validate(order);
    }
}

// 使用自定义接口
public class CustomFunctionalInterface {
    public static void main(String[] args) {
        List<Order> orders = createOrders();
        
        // 定义验证规则
        OrderValidator isActive = Order::isActive;
        OrderValidator isHighValue = o -> o.getAmount() > 1000;
        
        // 组合验证(利用默认方法)
        OrderValidator combined = isActive.and(isHighValue);
        
        // 应用验证
        orders.stream()
            .filter(combined::validate) // 方法引用
            .forEach(o -> System.out.println("Valid: " + o));
    }
}

2.4 阶段4:方法引用与构造函数引用

public class ReferenceDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Tom", "Jerry");

        // 1. 静态方法引用:类名::静态方法
        names.stream()
            .map(String::toUpperCase) // 等价于 s -> s.toUpperCase()
            .forEach(System.out::println);

        // 2. 实例方法引用:对象::实例方法
        String prefix = "Name: ";
        names.forEach(s -> System.out.println(prefix + s));

        // 3. 构造函数引用:类名::new
        Supplier<List<String>> listSupplier = ArrayList::new;
        List<String> newList = listSupplier.get();

        // 4. 数组构造函数引用:类型[]::new
        IntFunction<String[]> arrayCreator = String[]::new;
        String[] array = arrayCreator.apply(5); // 创建长度为5的数组
    }
}

2.5 阶段5:Stream API中的函数式接口应用

public class StreamFunctionalDemo {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
            new Employee("Alice", 8000, "Tech"),
            new Employee("Bob", 12000, "Tech"),
            new Employee("Charlie", 7000, "HR")
        );

        // 综合案例:分组、过滤、转换
        Map<String, List<String>> result = employees.stream()
            .filter(e -> e.getSalary() > 7500)  // Predicate
            .map(Employee::getName)             // Function
            .collect(Collectors.groupingBy(
                name -> name.substring(0, 1)    // Function
            ));

        System.out.println(result); // {A=[Alice], B=[Bob]}
    }
}

2.6 综合实战案例

// 构建一个函数式风格的订单处理系统
public class OrderProcessor {
    // 核心:用函数式接口定义可组合的业务规则
    private final Function<Order, Double> taxCalculator;
    private final Predicate<Order> validationRule;
    private final Consumer<Order> auditLogger;

    // 构造函数注入行为
    public OrderProcessor(Function<Order, Double> taxCalculator,
                         Predicate<Order> validationRule,
                         Consumer<Order> auditLogger) {
        this.taxCalculator = taxCalculator;
        this.validationRule = validationRule;
        this.auditLogger = auditLogger;
    }

    public void process(List<Order> orders) {
        orders.stream()
            .filter(validationRule)                    // 验证
            .peek(auditLogger)                         // 记录日志
            .map(order -> {                            // 计算税后价格
                double tax = taxCalculator.apply(order);
                order.setFinalPrice(order.getAmount() + tax);
                return order;
            })
            .forEach(order -> System.out.println("处理完成: " + order));
    }

    public static void main(String[] args) {
        // 配置不同的业务规则
        OrderProcessor domesticProcessor = new OrderProcessor(
            order -> order.getAmount() * 0.1,   // 10%税
            Order::isActive,                     // 仅处理激活订单
            o -> System.out.println("审计: " + o.getId())
        );

        domesticProcessor.process(createOrders());
    }
}

三、总结

在四大核心函数式函数式接口的基础上,还有BiFunction<T, U, R> - 双参数转换、UnaryOperator<T> - 一元操作、BinaryOperator<T> - 二元操作。简单来说,UnaryOperatorBinaryOperator并非新的概念,而是两大核心函数式接口的“特化”或“简化版”。它们与四大核心函数接口的关系是包含与被包含的关系,而非并列关系。

接口类型 方法签名 用途 示例
Consumer void accept(T t) 消费数据 forEach
Supplier T get() 提供数据 延迟初始化
Function<T, R> R apply(T t) 数据转换 map
Predicate boolean test(T t) 条件判断 filter
BiFunction<T, U, R> R apply(T t, U u) 双参数转换 合并操作
UnaryOperator T apply(T t) 一元操作 字符串处理
BinaryOperator T apply(T t1, T t2) 二元操作 数学运算
  • Function和 BiFunction​ 是基础且通用的转换接口,适用于各种复杂的类型转换场景。
  • UnaryOperator和 BinaryOperator​ 是前两者的特殊形式,专门用于输入输出类型一致的特定场景,使代码意图更明确。

如果有需要,也可以使用@FunctionalInterface注解来定制契合某个业务的函数式接口。

posted @ 2025-12-18 16:08  李子园的李  阅读(0)  评论(0)    收藏  举报