一、函数式接口的定义
函数式接口 (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 - 消费型接口
- @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- 供给型接口
- @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 - 函数型接口
- @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 - 断言型接口
- @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 - 双参数转换、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注解来定制契合某个业务的函数式接口。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |