Java Lambda表达式常用的函数式接口

网友投稿 288 2022-08-05


Java Lambda表达式常用的函数式接口

目录Supplier接口Consumer接口Predicate接口Function接口BiFunction接口基本数据类型Supplier相关的接口Consumer相关的接口Predicate相关的接口Function相关的接口

前言:

在java8支持Lambda表达式以后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口。它们主要在 java.util.function 包中,下面简单介绍几个其中的接口及其使用示例。

Supplier接口

Supplier接口是对象实例的提供者,定义了一个名叫get的抽象方法,它没有任何入参,并返回一个泛型T对象,具体源码如下:

package java.util.function;

@FunctionalInterface

public interface Supplier {

T get();

}

源码比较简单,我们来个例子。这是之前提过的表示口罩的类:

package one.more.study;

/**

* 口罩

*/

public class Mask {

public Mask(String brand, String type) {

this.branKxjcVOGd = brand;

this.type = type;

}

/**

* 品牌

*/

private String brand;

/**

* 类型

*/

private String type;

public String getBrand() {

return brand;

}

public void setBrand(String brand) {

this.brand = brand;

}

public String getType() {

return type;

}

public void setType(String type) {

this.type = type;

}

}

下面我们使用Lambda表达式声明一个Supplier的实例:

Supplier supplier = () -> new Mask("3M", "N95");

用它来创建品牌为3M、类型为N95的Mask实例:

Mask mask = supplier.get();

System.out.println("Brand: " + mask.getBrand() + ", Type: " + mask.getType());

运行结果如下:

Brand: 3M, Type: N95

特别需要注意的是,本例中每一次调用get方法都会创建新的对象。

Consumer接口

Consumer接口是一个类似消费者的接口,定义了一个名叫accept的抽象方法,它的入参是一个泛型T对象,没有任何返回(void),主要源码如下:

package java.util.function;

@FunctionalInterface

public interface Consumer {

void accept(T t);

}

结合上面的Supplier接口,我们来个例子:

Supplier supplier = () -> new Mask("3M", "N95");

Consumer consumer = (Mask mask) -> {

System.out.println("Brand: " + mask.getBrand() + ", Type: " + mask.getType());

};

consumer.accept(supplier.get());

首先使用Lambda表达式声明一个Supplier的实例,它是用来创建品牌为3M、类型为N95的Mask实例;再使用Lambda表达式声明一个Consumer的实例,它是用于打印出Mask实例的相关信息;最后Consumer消费了Supplier生产的Mask。

运行结果如下:

Brand: 3M, Type: N95

Predicate接口

Predicate接口是判断是与否的接口,定义了一个名叫test的抽象方法,它的入参是一个泛型T对象,并返回一个boolean类型,主要源码如下:

package java.util.function;

@FunctionalInterface

public interface Predicate {

boolean test(T t);

}

结合上面的Supplier接口,我们来个例子:

Supplier supplier = () -> new Mask("3M", "N95");

Predicate n95 = (Mask mask) -> "N95".equals(mask.getType());

Predicate kn95 = (Mask mask) -> "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

Function接口

Function接口是对实例进行处理转换的接口,定义了一个名叫apply的抽象方法,它的入参是一个泛型T对象,并返回一个泛型R对象,主要源码如下:

package java.util.function;

@FunctionalInterface

public interface Function {

R apply(T t);

}

结合上面的Supplier接口,我们来个例子:

Supplier supplier = () -> new Mask("3M", "N95");

Function brand = (Mask mask) -> mask.getBrand();

Function type = (Mask mask) -> 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的实例type,它是用于获取口罩的类型;最后分别用两个Function分析Supplier生产的Mask。

运行结果如下:

口罩品牌:3M口罩类型:N95

BiFunction接口

Function接口的入参只有一个泛型对象,JDK还为我们提供了两个泛型对象入参的接口:BiFunction接口,主要源码如下:

package java.util.function;

@FunctionalInterface

public interface BiFunction {

R apply(T t, U u);

}

我们可以用BiFunction接口传入两个String直接创建Mask实例:

BiFunction biFunction = (String brand, String type) -> new Mask(brand, type);

Mask mask = biFunction.apply("3M", "N95");

System.out.println("Brand: " + mask.getBrand() + ", Type: " + mask.getType());

运行结果如下:

Brand: 3M, Type: N95

基本数据类型

以上介绍的几个常用的函数式接口入参和返回,都是泛型对象的,也就是必须为引用类型。当我们传入或获取的是基本数据类型时,将会发生自动装箱和自动拆箱,带来不必要的性能损耗,比如:

Supplier<Long> supplier = () -> System.currentTimeMillis();

long timeMillis = supplier.get();

在上面例子里,发生了一次自动装箱(long被装箱为Long)和一次自动拆箱(Long被拆箱为long),如何避免这种不必要的性能损耗呢?JDK为我们提供相应的函数式接口,如LongSupplier接口,定义了一个名叫getAsLong的抽象方法,签名是() -> long。

上面的例子可以优化为:

LongSupplier supplier = () -> System.currentTimeMillis();

long timeMillis = supplier.getAsLong();

类似这样的接口还有很多,我为大家整理了一下:

Supplier相关的接口

接口名称方法名称方法签名Supplierget() -> TBooleanSuppliergetAsBoolean() -> booleanDoubleSuppliergetAsDouble() -> doubleIntSuppliergetAsInt() -> intLongSuppliergetAsLong() -> long

Consumer相关的接口

接口名称方法名称方法签名Consumeraccept(T) -> voidDoubleConsumeraccept(double) -> voidIntConsumeraccept(int) -> voidLongConsumeraccept(long) -> voidObjDoubleConsumeraccept(T, double) -> voidObjIntConsumeraccept(T, int) -> voidObjLongConsumeraccept(T, long) -> void

Predicate相关的接口

接口名称方法名称方法签名Predicatetest(T) -> booleanBiPredicatetest(T, U) -> booleanDoublePredicatetest(double) -> booleanIntPredicatetest(int) -> booleanLongPredicatetest(long) -> boolean

Function相关的接口

接口名称方法名称方法签名Functionapply(T) -> RBiFunctionapply(T, U) -> RDoubleFunctionapply(double) -> RDoubleToIntFunctionapplyAsInt(double) -> intDoubleToLongFunctionapplyAsLong(double) -> longIntFunctionapply(int) -> RIntToDoubleFunctionapplyAsDouble(int) -> doubleIntToLongFunctionapplyAsLong(int) -> longLongFunctionapply(long) -> RLongToDoubleFunctionapplyAsDoubhttp://le(long) -> doubleLongToIntFunctionapplyAsInt(long) -> intToDoubleFunctionapplyAsDouble(T) -> doubleToDoubleBiFunctionapplyAsDouble(T, U) -> doubleToIntFunctionapplyAsInt(T) -> intToIntBiFunctionapplyAsInt(T, U) -> intToLongFunctionapplyAsLong(T) -> longToLongBiFunctionapplyAsLong(T, U) -> long


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot整合logback的示例代码(springboot集成日志logback)
下一篇:Android Rxjava3 使用场景详解(android是什么系统)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~