失去了人性,失去了很多;失去了动物性,失去了一切。——《三体》Java8支持Lambda表达式后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口。它们主要在java.util.function包中。下面简单介绍其中的几个接口及其使用示例。Supplier接口Supplier接口是对象实例的提供者。它定义了一个名为get的抽象方法。它没有任何输入参数并返回一个通用的T对象。具体源码如下:packagejava.util.function;@FunctionalInterfacepublicinterfaceSupplier{Tget();}源码比较简单,举个例子。这是代表前面提到的面具的类:packageone.more.study;/***mask*/publicclassMask{publicMask(Stringbrand,Stringtype){this.brand=brand;this.type=类型;}/***brand*/private字符串品牌;/***类型*/私有字符串类型;publicStringgetBrand(){返回品牌;}publicvoidsetBrand(Stringbrand){this.brand=brand;}publicStringgetType(){返回类型;}publicvoidsetType(Stringtype){this.type=type;下面我们使用Lambda表达式声明一个Supplier实例:Suppliersupplier=()->newMask("3M","N95");使用它创建品牌为3M且类型为N95的Mask实例:Maskmask=supplier.get();System.out.println("Brand:"+mask.getBrand()+",Type:"+mask.getType());运行结果如下:品牌:3M,型号:N95需要注意的是,本例中每次调用get方法都会创建一个新的对象。Consumer接口Consumer接口是一个类似于消费者的接口。它定义了一个名为accept的抽象方法。它的输入参数是一个通用的T对象,没有任何返回值(void)。主要源码如下:packagejava.util.function;@FunctionalInterfacepublicinterfaceConsumer{voidaccept(Tt);}结合上面的Supplier接口,我们举个例子:Suppliersupplier=()->新口罩("3M","N95");Consumerconsumer=(Maskmask)->{System.out.println("Brand:"+mask.getBrand()+",Type:"+mask.getType());};consumer.accept(供应商。得到());首先,使用Lambda表达式声明一个Supplier实例,用于创建一个品牌为3M、型号为N95的Mask实例;然后使用Lambda表达式声明一个Consumer实例,用于打印出Mask实例的信息;最后,Consumer消费Supplier生产的Mask。运行结果如下:Brand:3M,Type:N95Predicate接口Predicate接口是一个判断是或否的接口,定义了一个名为test的抽象方法,其入参为泛型T对象,返回boolean类型,主要是源码如下:packagejava.util.function;@FunctionalInterfacepublicinterfacePredicate{booleantest(Tt);}结合上面的Supplier接口,我们举个例子:Suppliersupplier=()->newMask("3M","N95");Predicaten95=(Maskmask)->"N95".equals(mask.getType());Predicatekn95=(Maskmask)->"KN95".equals(mask.getType());System.out.println("是否是N95口罩:"+n95.test(supplier.get()));System.out.println("是否是KN95口罩:"+kn95.test(supplier.get()));首先,使用Lambda表达式声明一个Supplier实例,用于创建一个品牌为3M、型号为N95的Mask实例;然后使用Lambda表达式声明一个Predicate实例n95,用于判断是否为N95口罩;然后使用Lambda表达式声明一个Predicate实例kn95,用于判断是否为KN95口罩;最后用两个Predicate来判断Supplier生产的Mask。运行结果如下:是否是N95口罩:true是否是KN95口罩:false泛型T对象,并返回一个泛型R对象,主要源码如下:packagejava.util.function;@FunctionalInterfacepublicinterfaceFunction{Rapply(Tt);}结合上面的Supplier接口,我们举个例子:Suppliersupplier=()->newMask("3M","N95");Functionbrand=(Maskmask)->mask.getBrand();Functiontype=(Maskmask)->mask.getType();System.out.println("口罩品牌:"+brand.apply(supplier.get()));System.out.println("口罩类型:"+type.apply(supplier.get()));首先,使用Lambda表达式声明一个Supplier实例,用于创建一个品牌为3M、型号为N95的Mask实例;然后使用Lambda表达式声明一个Function实例brand,用于获取口罩的品牌;然后使用Lambda表达式声明一个Function实例类型,用于获取mask的类型;最后用两个Function来分析Supplier生产的Mask。运行结果如下:Mask品牌:3MMask类型:N95BiFunction接口Function接口的输入参数只有一个泛型对象,JDK也为我们提供了两个泛型对象输入接口:BiFunction接口,主要源码如下如下:包java。util.function;@FunctionalInterfacepublicinterfaceBiFunction{Rapply(Tt,Uu);}我们可以使用BiFunction接口传入两个String直接创建Mask实例:BiFunctionbiFunction=(Stringbrand,Stringtype)->newMask(brand,type);Maskmask=biFunction.apply("3M","N95");System.out.println("Brand:"+mask.getBrand()+",类型:"+mask.getType());运行结果如下:品牌:3M,类型:N95基本数据类型上面介绍的几种常用功能接口的输入和返回都是泛型对象,即必须是引用类型。当我们传入或获取基本数据类型时,会发生自动装箱和自动拆箱,这会带来不必要的性能损失,如:Suppliersupplier=()->System.currentTimeMillis();longtimeMillis=supplier.get();在上面的例子中,发生了一次自动装箱(longisboxedtoLong)和一次自动拆箱(Longisunboxedtolong),如何避免这种不必要的性能损失呢?JDK为我们提供了相应的函数式接口,比如LongSupplier接口,它定义了一个抽象方法getAsLong,其签名为()->long。上面的例子可以优化为:LongSuppliersupplier=()->System.currentTimeMillis();longtimeMillis=supplier.getAsLong();类似这样的接口还有很多,我给大家整理一下:Supplier相关的接口接口名MethodNameMethodSignatureSupplierget()->TBooleanSuppliergetAsBoolean()->booleanDoubleSuppliergetAsDouble()->doubleIntSuppliergetAsInt()->intLongSuppliergetAsLong()->longConsumer相关接口接口名称方法名称方法签名Consumeraccept(T)->voidDoubleConsumeraccept(double)->voidIntConsumeraccept(int)->voidLongConsumeraccept(long)->voidObjDoubleConsumeraccept(T,double)->voidObjIntConsumeraccept(T,int)->voidObjLongConsumeraccept(T,long)->voidPredicate相关接口接口名方法名方法签名Predicatetest(T)->booleanBiPredicatetest(T,U)->booleanDoublePredicatetest(double)->booleanIntPredicatetest(int)->booleanLongPredicatetest(long)->booleanFunction相关接口接口名称方法名称方法签名Functionapply(T)->RBiFunctionapply(T,U)->RDoubleFunctionapply(double)->RDoubleToIntFunctionapplyAsInt(double)->intDoubleToLongFunctionapplyAsLong(double)->longIntFunctionapply(int)->RIntToDoubleFunctionapplyAsDouble(int)->doubleIntToLongFunctionapplyAsLong(int)->longLongFunctionapply(long)->RLongToDoubleFunctionapplyAsDouble(long)->doubleLongToIntFunctionToubleAsDoubleFunction(long)应用->doubleToDoubleBiFunctionapplyAsDouble(T,U)->doubleToIntFunctionapplyAsInt(T)->intToIntBiFunctionapplyAsInt(T,U)->intToLongFunctionapplyAsLong(T)->longToLongBiFunctionapplyAsLong(T,U)->long