如何将渐进式学习应用于Java函数式接口?

摘要:一、函数式接口的定义 函数式接口 (Functional Interface) 是Java 8引入的核心概念,它是指有且仅有一个抽象方法的接口(可包含默认方法和静态方法)。这种接口可以用Lambda表达式或方法引用来实现,是函数式编程在Ja
一、函数式接口的定义 函数式接口 (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> - 二元操作。简单来说,UnaryOperator和BinaryOperator并非新的概念,而是两大核心函数式接口的“特化”或“简化版”。它们与四大核心函数接口的关系是包含与被包含的关系,而非并列关系。 接口类型 方法签名 用途 示例 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注解来定制契合某个业务的函数式接口。