java8 函数编程Consumer使用详解

x33g5p2x  于2022-06-27 转载在 Java  
字(3.6k)|赞(0)|评价(0)|浏览(677)

Consumer 源码

  1. package java.util.function;
  2. import java.util.Objects;
  3. @FunctionalInterface
  4. public interface Consumer<T> {
  5. void accept(T t);
  6. default Consumer<T> andThen(Consumer<? super T> after) {
  7. Objects.requireNonNull(after);
  8. return (T t) -> { accept(t); after.accept(t); };
  9. }
  10. }

从源码来看,Consumer函数主要有两个方法,accept和andThen。

Consumer 使用

演示一

建立演示方法:

  1. public static void t1(){
  2. Consumer<Integer> cal=x-> {
  3. x=x*10;
  4. System.out.println(x);
  5. };
  6. cal.accept(20);
  7. }

执行结果:

  1. 200

演示二

创建一个car汽车类

  1. /**
  2. * 汽车
  3. */
  4. public class Car {
  5. private String name;
  6. private String company;
  7. /**
  8. * 设置名称并返回当前对象
  9. * @param name
  10. * @return
  11. */
  12. public Car setName(String name){
  13. this.name=name;
  14. return this;
  15. }
  16. /**
  17. * 设置公司并返回当前类
  18. * @param company
  19. * @return
  20. */
  21. public Car setCompany(String company){
  22. this.company=company;
  23. return this;
  24. }
  25. @Override
  26. public String toString() {
  27. return "name:"+name+" company:"+company;
  28. }
  29. }

创建演示方法:

  1. public static void t2(Consumer<Car> consumer){
  2. Car car=new Car();
  3. consumer.accept(car);
  4. System.out.println(car.toString());
  5. }
  6. public static void main(String[] args) {
  7. t2(Car->Car.setName("长安cs 85").setCompany("长安"));
  8. }

执行结果:

  1. name:长安cs 85 company:长安

演示三

  1. public static void t3(){
  2. Consumer<Car> setNameFn=car -> {car.setName("长城H6汽车");};
  3. Consumer<Car> setCompanyFn=car -> {car.setCompany("长城公司");};
  4. Car car1=new Car();
  5. setNameFn.accept(car1);
  6. System.out.println(car1);
  7. Car car2=new Car();
  8. //使用andThen链接多个函数执行
  9. setNameFn.andThen(setCompanyFn).accept(car2);
  10. System.out.println(car2);
  11. }

执行结果:

  1. name:长城H6汽车 company:null
  2. name:长城H6汽车 company:长城公司

consumer从字面上面来理解就是消费的意思,用过mq的,应该大概可以了解到意思。

我们先来看看Java8定义的这个consumer的接口:

  1. @FunctionalInterface
  2. public interface Consumer<T> {
  3. void accept(T t);
  4. default Consumer<T> andThen(Consumer<? super T> after) {
  5. Objects.requireNonNull(after);
  6. return (T t) -> { accept(t); after.accept(t); };
  7. }
  8. }

该接口被@FunctionalInterface注解修饰,这个注解的意思代表的是这个接口只有一个抽象接口方法,如果超过一个,只不能不用该接口,会编译不通过。

该接口有一个抽象方法accept,接受的是泛型T的一个参数类型,这个方法是在consumer的实例显示被调用之后,那么指定的函数式表达式才会被执行,请看下面例子:​​​​​​​

  1. // 构造函数式表达,并赋值于consumer对象,其中此时泛型已经被指定为Integer了
  2. // 所以此时调用accept方法时,传入的对象必须一一对应传入Integer类型
  3. Consumer<Integer> consumer = x -> {
  4. int a = x + 2;
  5. System.out.println(a);// 12
  6. System.out.println(a + "_");// 12_
  7. };
  8. // 显示调用,consumer中的函数式方法才会调用,可以理解为预先
  9. // 定义好要执行的代码逻辑,等到要执行的时候才显示的执行,这在项目中
  10. // 的需求还是很大,比如数据还没有到达,则此时可以等到数据到达之后才调用
  11. consumer.accept(10);

该接口方法还有另外一个默认实现方法andThen,从方法名很容易知道,先执行本接口方法的accept方法,之后再执行after的accept方法,请看下面代码:​​​​​​​

  1. /**传入一个Consumer类型的参数,
  2. *他的泛型类型,
  3. *跟本接口是一致的T,先做本接口的accept操作,
  4. *然后在做传入的Consumer类型的参数的accept操作
  5. */
  6. default Consumer<T> andThen(Consumer<? super T> after) {
  7. Objects.requireNonNull(after);
  8. return (T t) -> { accept(t); after.accept(t); };
  9. }

例子:​​​​​​​

  1. public class TestConsumer {
  2. public static void main(String[] args) {
  3. // 定义第一个consumer表达式
  4. Consumer<Integer> consumer = x -> {
  5. int a = x + 2;
  6. System.out.println(a);// 8
  7. System.out.println(a + "_");// 8_
  8. };
  9. // 定义第二个consumer表达式
  10. Consumer<Integer> after = x -> {
  11. int a = x * 2;
  12. System.out.println(a);// 12
  13. System.out.println(a + "_");// 12_
  14. };
  15. // 调用方式,先执行第一个consumer表达式,执行完之后将参数直接传递给
  16. // 后面的after表达式继续执行,这个场景可以用于相同入参不同方法先后执行顺序,
  17. consumer.andThen(after).accept(6);
  18. }
  19. }

运行结果:

  1. 88_1212_

consumer是一个函数式接口(可以采用lambda写法),它的源码如下

  1. @FunctionalInterface
  2. public interface Consumer<T> {
  3. void accept(T t);
  4. default Consumer<T> andThen(Consumer<? super T> after) {
  5. Objects.requireNonNull(after);
  6. return (T t) -> { accept(t); after.accept(t); };
  7. }
  8. }

consumer的具体的使用场景就是可以提前记录我们的某些操作,然后在后面再去执行,比如说:当我们在a方法中,需要把某些参数赋值给一个Integer类型的对象,而该对象只有在b方法才能赋值,那么我们可以在a方法中使用consumer记录我们要执行的操作,再把consumer作为参数传递到b方法执行,多种操作可以用该接口的default方法addThen来持续记录

  1. a(int x, int y){
  2. Consumer<Integer> consumer = null;
  3. consumer = z -> z = x + 2;
  4. consumer.addThen(z -> z -= y);
  5. b(consumer);
  6. }
  7. b(Consumer<Integer> consumer){
  8. Integer z = 0;
  9. consumer.accept(z);
  10. }

相关文章

最新文章

更多