Java中Consumer与Supplier接口的使用及区别小结

 更新时间:2025年11月07日 08:33:45   作者:往事随风去  
Consumer和Supplier是Java8引入的两个函数式接口,Consumer用于消费数据,Supplier用于提供数据,两者都是函数式接口,本文就来介绍一下Java中Consumer与Supplier接口的使用及区别小结,感兴趣的可以了解一下

异同分析

Consumer 和 Supplier 是 Java 8 引入的两个重要函数式接口,位于 java.util.function 包中,用于支持函数式编程范式。

相同点

  1. 都是函数式接口(只有一个抽象方法)
  2. 都位于 java.util.function 包中
  3. 都用于 Lambda 表达式和方法引用
  4. 都在 Stream API 和 Optional 类中广泛使用

不同点

特性ConsumerSupplier
方法签名void accept(T t)T get()
参数接受一个输入参数无输入参数
返回值无返回值返回一个值
主要用途消费数据提供数据
类比方法中的参数方法中的返回值

详细分析与使用场景

Consumer 接口

Consumer 表示接受单个输入参数但不返回结果的操作。

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

public class ConsumerExample {
    public static void main(String[] args) {
        // 基本用法
        Consumer<String> printConsumer = s -> System.out.println(s);
        printConsumer.accept("Hello Consumer!");
        
        // 方法引用方式
        Consumer<String> methodRefConsumer = System.out::println;
        methodRefConsumer.accept("Hello Method Reference!");
        
        // 集合遍历中的应用
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        names.forEach(printConsumer);
        
        // andThen 方法组合多个 Consumer
        Consumer<String> upperCaseConsumer = s -> System.out.println(s.toUpperCase());
        Consumer<String> decoratedConsumer = s -> System.out.println("*** " + s + " ***");
        
        Consumer<String> combinedConsumer = upperCaseConsumer.andThen(decoratedConsumer);
        combinedConsumer.accept("functional interface");
        
        // 在 Optional 中的使用
        java.util.Optional<String> optional = java.util.Optional.of("Present");
        optional.ifPresent(combinedConsumer);
    }
}

Consumer 的使用场景

  1. 遍历集合元素并执行操作
  2. 处理数据并产生副作用(如打印、保存到数据库)
  3. 在 Optional 中处理可能存在的值
  4. 组合多个操作形成处理链

Supplier 接口

Supplier 表示一个供应商,不需要传入参数但返回一个值。

import java.util.function.Supplier;
import java.util.List;
import java.util.Random;
import java.util.stream.Stream;

public class SupplierExample {
    public static void main(String[] args) {
        // 基本用法
        Supplier<String> stringSupplier = () -> "Hello from Supplier!";
        System.out.println(stringSupplier.get());
        
        // 方法引用方式
        Supplier<Double> randomSupplier = Math::random;
        System.out.println("Random number: " + randomSupplier.get());
        
        // 对象工厂
        Supplier<List<String>> listSupplier = () -> java.util.Arrays.asList("A", "B", "C");
        System.out.println("List from supplier: " + listSupplier.get());
        
        // 延迟计算/初始化
        Supplier<ExpensiveObject> expensiveObjectSupplier = () -> {
            System.out.println("Creating expensive object...");
            return new ExpensiveObject();
        };
        
        System.out.println("Supplier created but no object yet...");
        // 只有在调用 get() 时才会创建对象
        ExpensiveObject obj = expensiveObjectSupplier.get();
        
        // 在 Stream 中生成无限流
        Supplier<Integer> randomIntSupplier = () -> new Random().nextInt(100);
        Stream.generate(randomIntSupplier)
              .limit(5)
              .forEach(System.out::println);
              
        // 在 Optional 中作为备选值
        java.util.Optional<String> emptyOptional = java.util.Optional.empty();
        String value = emptyOptional.orElseGet(() -> "Default from supplier");
        System.out.println("Value from empty optional: " + value);
    }
    
    static class ExpensiveObject {
        ExpensiveObject() {
            // 模拟耗时操作
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
        }
    }
}

Supplier 的使用场景

  1. 延迟初始化或延迟计算
  2. 提供配置或默认值
  3. 生成测试数据或模拟对象
  4. 在 Optional 中提供备选值
  5. 创建对象工厂
  6. 实现惰性求值模式

实际应用示例

下面是一个结合使用 Consumer 和 Supplier 的示例:

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

public class CombinedExample {
    private static final Logger logger = Logger.getLogger(CombinedExample.class.getName());
    
    public static void main(String[] args) {
        // 创建一个数据处理器,结合了 Supplier 和 Consumer
        processData(
            () -> { // Supplier - 提供数据
                // 模拟从数据库或API获取数据
                return new String[] {"Data1", "Data2", "Data3"};
            },
            data -> { // Consumer - 处理数据
                for (String item : data) {
                    System.out.println("Processing: " + item);
                }
            },
            error -> { // Consumer - 错误处理
                logger.severe("Error occurred: " + error.getMessage());
            }
        );
    }
    
    public static <T> void processData(Supplier<T> dataSupplier, 
                                      Consumer<T> dataProcessor, 
                                      Consumer<Exception> errorHandler) {
        try {
            T data = dataSupplier.get(); // 从Supplier获取数据
            dataProcessor.accept(data);  // 用Consumer处理数据
        } catch (Exception e) {
            errorHandler.accept(e);      // 用Consumer处理错误
        }
    }
}

总结

  • Consumer 用于表示接受输入并执行操作但不返回结果的函数,常见于需要处理数据并产生副作用的场景
  • Supplier 用于表示无需输入但返回结果的函数,常见于延迟计算、提供数据和工厂模式场景
  • 两者都是函数式编程中的重要构建块,可以组合使用创建灵活的数据处理管道
  • 在 Stream API、Optional 和现代 Java 框架中广泛应用

理解这两个接口的差异和适用场景有助于编写更简洁、更表达力的 Java 代码,特别是在使用 Stream API 和函数式编程范式时。

到此这篇关于Java中Consumer与Supplier接口的使用及区别小结的文章就介绍到这了,更多相关Java Consumer与Supplier接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇文章告诉你如何在Java数组中插入一个字符

    一篇文章告诉你如何在Java数组中插入一个字符

    本篇文章主要介绍了Java数组中插入一个字符的相关方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-10-10
  • Mybatis-plus配置多数据源,连接多数据库方式

    Mybatis-plus配置多数据源,连接多数据库方式

    这篇文章主要介绍了Mybatis-plus配置多数据源,连接多数据库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • php上传文件分类实例代码

    php上传文件分类实例代码

    这篇文章主要介绍了php上传文件分类实例代码,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-02-02
  • maven多模块项目依赖管理与依赖继承详解

    maven多模块项目依赖管理与依赖继承详解

    这篇文章主要介绍了maven多模块项目依赖管理与依赖继承详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java中自定义LRU缓存详解

    Java中自定义LRU缓存详解

    这篇文章主要介绍了Java中自定义LRU缓存详解,基于LRU算法的缓存系统,可以在达到缓存容量上限时,清理最近最少使用的数据,为新的数据的插入腾出空间,需要的朋友可以参考下
    2023-09-09
  • Spring Aop如何给Advice传递参数

    Spring Aop如何给Advice传递参数

    这篇文章主要介绍了Spring Aop如何给Advice传递参数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • idea启动项目提示端口占用的问题解决

    idea启动项目提示端口占用的问题解决

    有时候当我们使用Tomcat启动web项目时,会提示端口占用,导致启动失败,本文就来介绍一下端口占用的解决方法,具有一定的参考价值,感兴趣的可以了解下
    2023-08-08
  • 详解Java深拷贝,浅拷贝和Cloneable接口

    详解Java深拷贝,浅拷贝和Cloneable接口

    这篇文章主要为大家详细介绍了Java中Cloneable接口以及深拷贝与浅拷贝的相关知识,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-08-08
  • 详解SpringBoot中自定义starter的开发与使用

    详解SpringBoot中自定义starter的开发与使用

    starter是SpringBoot中非常重要的一个机制,他是基于约定优于配置的思想所衍生出来的,本文主要介绍了SpringBoot中自定义starter的开发与使用,感兴趣的可以了解下
    2023-09-09
  • SpringBoot整合Redis实现刷票过滤功能

    SpringBoot整合Redis实现刷票过滤功能

    随着互联网的不断发展,网站或APP的用户流量增加,也衍生出了一些恶意刷量等问题,给数据分析及运营带来极大的困难,所以本文使用SpringBoot和Redis实现一个刷票过滤功能,需要的可以参考一下
    2023-06-06

最新评论