找回密码
 立即注册
首页 业界区 业界 Java函数式接口——渐进式学习

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

列蜜瘘 2 小时前
一、函数式接口的定义

函数式接口 (Functional Interface) 是Java 8引入的核心概念,它是指有且仅有一个抽象方法的接口(可包含默认方法和静态方法)。这种接口可以用Lambda表达式方法引用来实现,是函数式编程在Java中的基础。
  1. // 标准定义
  2. @FunctionalInterface  // 编译期检查,可选但推荐
  3. public interface MyFunction {
  4.     String apply(int x);  // 唯一的抽象方法
  5.     // 允许默认方法
  6.     default void print(String msg) {
  7.         System.out.println(msg);
  8.     }
  9.     // 允许静态方法
  10.     static void log(String msg) {
  11.         System.out.println("[LOG] " + msg);
  12.     }
  13. }
复制代码
二、渐进式学习——代码示例

2.1 阶段1:从匿名类到Lambda演化
  1. public class EvolutionDemo {
  2.     public static void main(String[] args) {
  3.         List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
  4.         // 【传统方式】匿名内部类
  5.         names.forEach(new Consumer<String>() {
  6.             @Override
  7.             public void accept(String name) {
  8.                 System.out.println(name);
  9.             }
  10.         });
  11.         // 【方式1】Lambda完整语法
  12.         names.forEach((String name) -> {
  13.             System.out.println(name);
  14.         });
  15.         // 【方式2】Lambda简化(参数类型推导)
  16.         names.forEach((name) -> System.out.println(name));
  17.         // 【方式3】Lambda最简(单参数可省括号)
  18.         names.forEach(name -> System.out.println(name));
  19.         // 【方式4】方法引用(终极简化)
  20.         names.forEach(System.out::println);
  21.     }
  22. }
复制代码
2.2 阶段2:Java内置的四大核心函数式接口精讲

1. Consumer - 消费型接口
  1. @FunctionalInterface
  2. public interface Consumer<T> {
  3.     void accept(T t);
  4. }
复制代码
作用:接收一个参数,不返回结果
示例:
  1. // 打印字符串
  2. Consumer<String> printer = s -> System.out.println(s);
  3. printer.accept("Hello, Consumer!");
  4. // 消费列表元素
  5. List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
  6. names.forEach(name -> System.out.println("Hello, " + name));
复制代码
2. Supplier- 供给型接口
  1. @FunctionalInterface
  2. public interface Supplier<T> {
  3.     T get();
  4. }
复制代码
作用:不接收参数,返回一个结果
示例:
  1. // 生成随机数
  2. Supplier<Double> randomSupplier = () -> Math.random();
  3. System.out.println("Random: " + randomSupplier.get());
  4. // 延迟初始化
  5. Supplier<String> lazyString = () -> {
  6.     System.out.println("Initializing...");
  7.     return "Lazy Value";
  8. };
  9. System.out.println("Before get");
  10. System.out.println(lazyString.get());
复制代码
3. Function - 函数型接口
  1. @FunctionalInterface
  2. public interface Function<T, R> {
  3.     R apply(T t);
  4. }
复制代码
作用:接收一个参数,返回一个结果
示例:
  1. // 字符串转整数
  2. Function<String, Integer> stringToInt = s -> Integer.parseInt(s);
  3. int result = stringToInt.apply("123");
  4. System.out.println("Result: " + result);
  5. // 函数组合
  6. Function<Integer, Integer> doubleIt = x -> x * 2;
  7. Function<Integer, Integer> addOne = x -> x + 1;
  8. Function<Integer, Integer> composed = doubleIt.andThen(addOne);
  9. System.out.println("Composed: " + composed.apply(5)); // 输出: 11
复制代码
4. Predicate - 断言型接口
  1. @FunctionalInterface
  2. public interface Predicate<T> {
  3.     boolean test(T t);
  4. }
复制代码
作用:接收一个参数,返回布尔值
示例:
  1. // 判断字符串是否为空
  2. Predicate<String> isEmpty = s -> s == null || s.isEmpty();
  3. System.out.println("Is empty: " + isEmpty.test("")); // true
  4. // 过滤列表
  5. List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
  6. List<Integer> evenNumbers = numbers.stream()
  7.     .filter(n -> n % 2 == 0)
  8.     .collect(Collectors.toList());
  9. System.out.println("Even numbers: " + evenNumbers); // [2, 4, 6]
复制代码
2.3 阶段3:自定义函数式接口实践
  1. // 定义业务相关的函数式接口
  2. @FunctionalInterface
  3. interface OrderValidator {
  4.     boolean validate(Order order);
  5.    
  6.     // 默认方法:组合验证
  7.     default OrderValidator and(OrderValidator other) {
  8.         return order -> this.validate(order) && other.validate(order);
  9.     }
  10. }
  11. // 使用自定义接口
  12. public class CustomFunctionalInterface {
  13.     public static void main(String[] args) {
  14.         List<Order> orders = createOrders();
  15.         
  16.         // 定义验证规则
  17.         OrderValidator isActive = Order::isActive;
  18.         OrderValidator isHighValue = o -> o.getAmount() > 1000;
  19.         
  20.         // 组合验证(利用默认方法)
  21.         OrderValidator combined = isActive.and(isHighValue);
  22.         
  23.         // 应用验证
  24.         orders.stream()
  25.             .filter(combined::validate) // 方法引用
  26.             .forEach(o -> System.out.println("Valid: " + o));
  27.     }
  28. }
复制代码
2.4 阶段4:方法引用与构造函数引用
  1. public class ReferenceDemo {
  2.     public static void main(String[] args) {
  3.         List<String> names = Arrays.asList("Tom", "Jerry");
  4.         // 1. 静态方法引用:类名::静态方法
  5.         names.stream()
  6.             .map(String::toUpperCase) // 等价于 s -> s.toUpperCase()
  7.             .forEach(System.out::println);
  8.         // 2. 实例方法引用:对象::实例方法
  9.         String prefix = "Name: ";
  10.         names.forEach(s -> System.out.println(prefix + s));
  11.         // 3. 构造函数引用:类名::new
  12.         Supplier<List<String>> listSupplier = ArrayList::new;
  13.         List<String> newList = listSupplier.get();
  14.         // 4. 数组构造函数引用:类型[]::new
  15.         IntFunction<String[]> arrayCreator = String[]::new;
  16.         String[] array = arrayCreator.apply(5); // 创建长度为5的数组
  17.     }
  18. }
复制代码
2.5 阶段5:Stream API中的函数式接口应用
  1. public class StreamFunctionalDemo {
  2.     public static void main(String[] args) {
  3.         List<Employee> employees = Arrays.asList(
  4.             new Employee("Alice", 8000, "Tech"),
  5.             new Employee("Bob", 12000, "Tech"),
  6.             new Employee("Charlie", 7000, "HR")
  7.         );
  8.         // 综合案例:分组、过滤、转换
  9.         Map<String, List<String>> result = employees.stream()
  10.             .filter(e -> e.getSalary() > 7500)  // Predicate
  11.             .map(Employee::getName)             // Function
  12.             .collect(Collectors.groupingBy(
  13.                 name -> name.substring(0, 1)    // Function
  14.             ));
  15.         System.out.println(result); // {A=[Alice], B=[Bob]}
  16.     }
  17. }
复制代码
2.6 综合实战案例
  1. // 构建一个函数式风格的订单处理系统
  2. public class OrderProcessor {
  3.     // 核心:用函数式接口定义可组合的业务规则
  4.     private final Function<Order, Double> taxCalculator;
  5.     private final Predicate<Order> validationRule;
  6.     private final Consumer<Order> auditLogger;
  7.     // 构造函数注入行为
  8.     public OrderProcessor(Function<Order, Double> taxCalculator,
  9.                          Predicate<Order> validationRule,
  10.                          Consumer<Order> auditLogger) {
  11.         this.taxCalculator = taxCalculator;
  12.         this.validationRule = validationRule;
  13.         this.auditLogger = auditLogger;
  14.     }
  15.     public void process(List<Order> orders) {
  16.         orders.stream()
  17.             .filter(validationRule)                    // 验证
  18.             .peek(auditLogger)                         // 记录日志
  19.             .map(order -> {                            // 计算税后价格
  20.                 double tax = taxCalculator.apply(order);
  21.                 order.setFinalPrice(order.getAmount() + tax);
  22.                 return order;
  23.             })
  24.             .forEach(order -> System.out.println("处理完成: " + order));
  25.     }
  26.     public static void main(String[] args) {
  27.         // 配置不同的业务规则
  28.         OrderProcessor domesticProcessor = new OrderProcessor(
  29.             order -> order.getAmount() * 0.1,   // 10%税
  30.             Order::isActive,                     // 仅处理激活订单
  31.             o -> System.out.println("审计: " + o.getId())
  32.         );
  33.         domesticProcessor.process(createOrders());
  34.     }
  35. }
复制代码
三、总结

在四大核心函数式函数式接口的基础上,还有BiFunction - 双参数转换、UnaryOperator - 一元操作、BinaryOperator - 二元操作。简单来说,UnaryOperator和BinaryOperator并非新的概念,而是两大核心函数式接口的“特化”或“简化版”。它们与四大核心函数接口的关系是包含与被包含的关系,而非并列关系。
接口类型方法签名用途示例Consumervoid accept(T t)消费数据forEachSupplierT get()提供数据延迟初始化FunctionR apply(T t)数据转换mapPredicateboolean test(T t)条件判断filterBiFunctionR apply(T t, U u)双参数转换合并操作UnaryOperatorT apply(T t)一元操作字符串处理BinaryOperatorT apply(T t1, T t2)二元操作数学运算

  • Function和 BiFunction​ 是基础且通用的转换接口,适用于各种复杂的类型转换场景。
  • UnaryOperator和 BinaryOperator​ 是前两者的特殊形式,专门用于输入输出类型一致的特定场景,使代码意图更明确。
如果有需要,也可以使用@FunctionalInterface注解来定制契合某个业务的函数式接口。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册