首页 > 编程语言 >探索Java8:(五)Supplier和Consumer接口的使用

探索Java8:(五)Supplier和Consumer接口的使用

时间:2022-09-21 10:13:09浏览次数:98  
标签:code after public Supplier operation Consumer Java8

Supplier是函数式编程的另一个接口,与Function、Predicate接口类似,区别在于Supplier不接收任何参数,只返回结果。

Supplier的基本使用

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

使用Supplier也很简单,与Function接口一样,Supplier使用lambda表达式和方法引用来实例化。

public class SupplierTest {
  public static void main(String[] args) {
     Supplier<String> supplier1 = () ->10; 
     System.out.println(supplier1.get());

     LocalDateTime now = LocalDateTime.now();
     Supplier<String> supplier2 =()->now.toString();
     //也可以使用Supplier<String> supplier2 = now::toString
     System.out.println(supplier2.get());     
  }
} 

指定类型的Supplier

除了Supplie以外,Java8中还提供了BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier。以LongSupplier为例

@FunctionalInterface
public interface LongSupplier {

    /**
     * Gets a result.
     *
     * @return a result
     */
    long getAsLong();
}

通过源码我们可以看到,LongSupplier相当于是一个指定了返回参数类型的Supplier。建议这种带类型的函数式接口可以结合起来看,可以同时看下LongFunction、LongConsumer、LongPredicate。

public class LongSupplierTest {
  public static void main(String[] args) {
     LongSupplier supplier1 = () ->1000L; 
     System.out.println(supplier1.getAsLong());
  }
} 

自定义Supplier

我们也可以使用@FunctionalInterface 注解来自定义一个Supplier类。

import java.util.Random;

@FunctionalInterface
interface UserSupplier {
    User getUser();
}
class User{
   private String username;
   private String password;
   public User(){
      this.usename="test";
      this.password="test";
   }
}
public class CustomSupplierDemo {
  public static void main(String[] args) {
     UserSupplier s1=User::new;
     System.out.println(s1.getUser());
  }
} 

Consumer的基本使用

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Consumer和Supplier正好相反,Consumer接收一个参数,但不返回任何结果。可以把Consumer看成是消费者,Supplier看成是生产者。Consumer支持复合操作,可以使用andThen()来连接其他的Consumer完成对同一参数的多次消费。注意:Consumer不返回结果,因此复合消费其实是对传入参数的多次消费,并改变上一次消费的参数。这点要与Function有所区别。

我们举个例子来说明一下:

public class ConsumerTest {
  public static void main(String[] args) {
     Supplier<String> supplier2 =()->"Hello World!";
     Consumer<String> consumer1=c-> System.out.println(c.toLowerCase());
     Consumer<String> consumer2=c-> System.out.println(c.toUpperCase());
     consumer1.accept(s1.get());
     //多次消费操作
     consumer1.andThen(consumer2).accept(s1.get());

  }
} 

hello world!
hello world!
HELLO WORLD!

使用场景

Supplier比较常用的场景是提供一个返回结果。比如从HTTP请求中获取一个值,这个操作可以用Supplier包装起来。虽然Supplier可以返回静态的字符串或者其他对象,但实际开发中这样的业务逻辑不如直接写一个方法进行返回来的简单明了。Supplier真正的用武之地是对一个复杂操作返回结果进行包装。

Consumer的常用场景是对已有数据的处理,比如创建一个对象之后发送到kafka、redis、写入数据库等。
总之,函数式编程应该用在抽象层次高、复用多的场景,而不是单纯业务逻辑的简单使用(反而影响代码的可阅读性)。找到具体场景中的最佳实践才能发挥函数式编程最大优点。

标签:code,after,public,Supplier,operation,Consumer,Java8
From: https://www.cnblogs.com/rever/p/16714618.html

相关文章

  • Java8日期处理
    Java8推出了新的日期API序号类描述1Instant时间戳2Duration持续时间,时间差3LocalDate只包含日期,例如:2022-09-194LocalTime只包含时间,例如:10:......
  • 面试题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费
     问题:一个consumer订阅两个topic,其中一个topic消息过多堆积了,会影响另一个topic消费吗答案:不影响。为什么呢?因为rocketmq首先对消息进行负载均衡(rebalance),就是将topic中......
  • 【java8新特性】02:常见的函数式接口
    Jdk8提供的函数式接口都在java.util.function包下,Jdk8的函数式类型的接口都有@FunctionInterface注解所标注,但实际上即使没有该注解标注的有且只有一个抽象方法的接口,都可......
  • Java8新特性
    1.lambda表达式即允许将函数作为参数传递进方法中。可以替代匿名内部类的编写新手一开始不能直接写出lambda表达式,我们可以先用Idea的提示写出匿名内部类,匿名内部类比较......
  • Java8/18
    Java流程控制1.用户交互ScannerScanner是Java5提供的一个工具类(java.until.Scanner),用来获取用户的输入,实现人机交互。基本语法:Scanners=newScanner(System.in);......
  • Java8/18
    Java方法1.方法概念eg:System.out.println();----System是一个系统类,out是System类的一个输出对象,println()就是一个方法什么是方法:Java方法是语句的集合,他们在一起执行......
  • 在consumer producer运行时停止kafka服务端会怎样
    结论服务端停止时,客户端程序会报错;服务端启动后,客户端程序能继续运行。也就是,消费者线程并未异常退出。实验步骤(1)停止后,consumer和producer会报错。消费者:.___......
  • JAVA8 - 流
    packagecom.day01;importorg.junit.Test;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.List;importjava.util.stream.Stream;/***......
  • 【java8新特性】01:函数式编程及Lambda入门
    我们首先需要先了解什么是函数式编程、函数式编程是一种结构化编程范式、类似于数学函数、它关注的重点在于数据操作、或者说它所提倡的思想是做什么,而不是如何去做。自J......
  • 在producer/consumer运行时删除topic会怎么样
    broker端有个参数(kafka_2.13-3.2.1/config/server.properties),auto.create.topics.enable,默认为true。意思是,当生产者、消费者读写一个不存在的topic时,是否自动创建该topic......