Java 函数式接口:Supplier 和 Consumer 使用示例

SupplierConsumer 是 Java 8 中引入的两个核心函数式接口,它们分别代表"生产者"和"消费者"的概念。下面我将通过几个实用的示例来展示它们的使用方法。

1. 基础概念

  • Supplier: 无参数,返回一个结果。方法签名:T get()
  • Consumer: 接受一个参数,不返回结果。方法签名:void accept(T t)

2. 基本使用示例

Supplier 示例

import java.util.function.Supplier;
import java.time.LocalDateTime;
import java.util.Random;

public class SupplierDemo {
    public static void main(String[] args) {
        // 示例1: 获取当前时间
        Supplier<LocalDateTime> currentTimeSupplier = () -> LocalDateTime.now();
        System.out.println("当前时间: " + currentTimeSupplier.get());
        
        // 示例2: 生成随机数
        Supplier<Integer> randomSupplier = () -> new Random().nextInt(100);
        System.out.println("随机数: " + randomSupplier.get());
        
        // 示例3: 延迟初始化(懒加载)
        Supplier<ExpensiveObject> expensiveObjectSupplier = () -> {
            System.out.println("创建昂贵对象...");
            return new ExpensiveObject();
        };
        
        System.out.println("Supplier创建了,但对象尚未初始化");
        // 只有当调用get()时,对象才会被创建
        ExpensiveObject obj = expensiveObjectSupplier.get();
    }
    
    static class ExpensiveObject {
        ExpensiveObject() {
            // 模拟耗时操作
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
        }
    }
}

Consumer 示例

import java.util.function.Consumer;
import java.util.Arrays;
import java.util.List;

public class ConsumerDemo {
    public static void main(String[] args) {
        // 示例1: 简单消费
        Consumer<String> printConsumer = s -> System.out.println(s);
        printConsumer.accept("Hello, Consumer!");
        
        // 示例2: 集合遍历
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        names.forEach(printConsumer);
        
        // 示例3: 链式操作
        Consumer<String> upperCaseConsumer = s -> System.out.println(s.toUpperCase());
        Consumer<String> decoratedConsumer = s -> System.out.println("*** " + s + " ***");
        
        // 使用andThen组合多个Consumer
        Consumer<String> combinedConsumer = printConsumer.andThen(upperCaseConsumer).andThen(decoratedConsumer);
        combinedConsumer.accept("Functional Interface");
    }
}

3. 实际应用场景

场景1: 日志记录

import java.util.function.Supplier;
import java.util.function.Consumer;

public class LoggerExample {
    // 使用Supplier延迟日志消息的计算(只有在需要记录时才计算)
    public static void logIfNeeded(boolean condition, Supplier<String> messageSupplier) {
        if (condition) {
            System.out.println(messageSupplier.get());
        }
    }
    
    // 使用Consumer处理日志输出(可以灵活替换输出方式)
    public static void processWithLogging(String data, Consumer<String> logger) {
        logger.accept("开始处理: " + data);
        // 处理逻辑...
        logger.accept("处理完成: " + data);
    }
    
    public static void main(String[] args) {
        // 只有在需要记录时才构建复杂的日志消息
        logIfNeeded(true, () -> "这是一个复杂的日志消息: " + System.currentTimeMillis());
        
        // 可以灵活切换日志输出方式
        Consumer<String> consoleLogger = System.out::println;
        Consumer<String> fileLogger = message -> {
            // 这里简化实现,实际中会写入文件
            System.out.println("写入文件: " + message);
        };
        
        processWithLogging("测试数据", consoleLogger);
        processWithLogging("重要数据", fileLogger);
    }
}

场景2: 数据验证和处理

import java.util.function.Consumer;
import java.util.ArrayList;
import java.util.List;

public class ValidationExample {
    public static void main(String[] args) {
        List<String> emails = new ArrayList<>();
        emails.add("valid@example.com");
        emails.add("invalid-email");
        emails.add("another@test.com");
        
        // 定义不同的处理器
        Consumer<String> emailValidator = email -> {
            if (!email.contains("@")) {
                System.out.println("无效邮箱: " + email);
            }
        };
        
        Consumer<String> emailProcessor = email -> {
            if (email.contains("@")) {
                System.out.println("处理邮箱: " + email);
            }
        };
        
        // 组合使用
        Consumer<String> emailHandler = emailValidator.andThen(emailProcessor);
        
        // 处理所有邮箱
        emails.forEach(emailHandler);
    }
}

场景3: 资源管理

import java.util.function.Consumer;
import java.util.function.Supplier;

public class ResourceManager {
    // 使用Supplier提供资源,Consumer处理资源
    public static <T> void withResource(Supplier<T> resourceSupplier, Consumer<T> resourceConsumer) {
        T resource = resourceSupplier.get();
        try {
            resourceConsumer.accept(resource);
        } finally {
            // 这里简化实现,实际中可能需要关闭资源
            System.out.println("清理资源: " + resource.getClass().getSimpleName());
        }
    }
    
    public static void main(String[] args) {
        // 模拟数据库连接
        Supplier<DatabaseConnection> dbConnectionSupplier = () -> {
            System.out.println("建立数据库连接...");
            return new DatabaseConnection();
        };
        
        Consumer<DatabaseConnection> dbQuery = connection -> {
            System.out.println("执行查询...");
            // 实际查询操作...
        };
        
        // 自动管理资源
        withResource(dbConnectionSupplier, dbQuery);
    }
    
    static class DatabaseConnection {
        // 模拟数据库连接
    }
}

场景4: 配置灵活的业务流程

import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.List;
import java.util.ArrayList;

public class OrderProcessor {
    public static void main(String[] args) {
        // 定义订单创建器
        Supplier<Order> orderSupplier = () -> new Order("ORD-001", 100.0);
        
        // 定义不同的订单处理器
        List<Consumer<Order>> processors = new ArrayList<>();
        processors.add(order -> order.applyDiscount(0.1)); // 打9折
        processors.add(order -> order.addTax(0.08)); // 加8%税
        processors.add(order -> System.out.println("订单处理完成: " + order));
        
        // 处理订单
        Order order = orderSupplier.get();
        processors.forEach(processor -> processor.accept(order));
    }
    
    static class Order {
        private String id;
        private double amount;
        
        public Order(String id, double amount) {
            this.id = id;
            this.amount = amount;
        }
        
        public void applyDiscount(double rate) {
            this.amount *= (1 - rate);
            System.out.println("应用折扣: " + (rate * 100) + "%");
        }
        
        public void addTax(double rate) {
            this.amount *= (1 + rate);
            System.out.println("添加税费: " + (rate * 100) + "%");
        }
        
        @Override
        public String toString() {
            return "Order{id='" + id + "', amount=" + amount + "}";
        }
    }
}

4. 高级用法:组合与柯里化

import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.function.Function;

public class AdvancedExamples {
    public static void main(String[] args) {
        // 组合多个Consumer
        Consumer<String> logStep1 = s -> System.out.println("步骤1: " + s);
        Consumer<String> logStep2 = s -> System.out.println("步骤2: " + s);
        Consumer<String> logStep3 = s -> System.out.println("步骤3: " + s);
        
        Consumer<String> fullProcess = logStep1.andThen(logStep2).andThen(logStep3);
        fullProcess.accept("处理数据");
        
        // 使用Supplier和Function创建处理管道
        Supplier<String> dataSupplier = () -> "原始数据";
        Function<String, String> step1 = s -> s + " -> 步骤1处理";
        Function<String, String> step2 = s -> s + " -> 步骤2处理";
        Function<String, String> step3 = s -> s + " -> 步骤3处理";
        
        String result = step1.andThen(step2).andThen(step3).apply(dataSupplier.get());
        System.out.println("最终结果: " + result);
    }
}

总结

SupplierConsumer 接口的主要优势:

  1. 延迟执行:Supplier 可以延迟计算,直到真正需要结果时才执行
  2. 代码解耦:将数据的生产(Supplier)和消费(Consumer)分离
  3. 灵活性:可以轻松替换不同的实现,而不需要修改主要逻辑
  4. 组合性:通过 andThen 方法可以轻松组合多个操作

在实际开发中,合理使用这些函数式接口可以使代码更加简洁、灵活和可维护。

更多推荐