java8 函数编程Consumer使用详解

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

Consumer 源码

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

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

Consumer 使用

演示一

建立演示方法:

public static void t1(){
        Consumer<Integer> cal=x-> {
            x=x*10;
            System.out.println(x);
        };
        cal.accept(20);
    }

执行结果:

200

演示二

创建一个car汽车类

/**
 * 汽车
 */
public class Car {

   private String name;
   private String company;
    /**
     * 设置名称并返回当前对象
     * @param name
     * @return
     */
    public Car setName(String name){
        this.name=name;
        return this;
    }

    /**
     * 设置公司并返回当前类
     * @param company
     * @return
     */
    public Car setCompany(String company){
        this.company=company;
        return this;
    }

    @Override
    public String toString() {
        return "name:"+name+" company:"+company;
    }
}

创建演示方法:

public static void t2(Consumer<Car> consumer){
        Car car=new Car();
        consumer.accept(car);
        System.out.println(car.toString());
    }

    public static void main(String[] args) {

        t2(Car->Car.setName("长安cs 85").setCompany("长安"));

    }

执行结果:

name:长安cs 85 company:长安

演示三

public static void t3(){
        Consumer<Car> setNameFn=car -> {car.setName("长城H6汽车");};
        Consumer<Car> setCompanyFn=car -> {car.setCompany("长城公司");};
        Car car1=new Car();
        setNameFn.accept(car1);
        System.out.println(car1);

        Car car2=new Car();
        //使用andThen链接多个函数执行
        setNameFn.andThen(setCompanyFn).accept(car2);
        System.out.println(car2);
    }

执行结果:

name:长城H6汽车 company:null
name:长城H6汽车 company:长城公司

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

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

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
 
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

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

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

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

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

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

例子:​​​​​​​

public class TestConsumer {

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

    }
}

运行结果:

88_1212_

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

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);
 
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

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

a(int x, int y){
	Consumer<Integer> consumer = null;
	consumer = z -> z = x + 2;
	consumer.addThen(z -> z -= y);
	b(consumer);
}

b(Consumer<Integer> consumer){
	Integer z = 0;
	consumer.accept(z);
}

相关文章