欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

死磕Lambda表达式(四):常用的函数式接口

程序员文章站 2022-05-23 18:53:47
在Java8支持Lambda表达式以后,为了满足Lambda表达式的一些典型使用场景,JDK为我们提供了大量常用的函数式接口。它们主要在 java.util.function 包中,下面简单介绍几个其中的接口及其使用示例。 ......

失去人性,失去很多;失去兽性,失去一切。——《三体》

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

supplier接口

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

package java.util.function;

@functionalinterface
public interface supplier<t> {
    t get();
}

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

package one.more.study;

/**
 * 口罩
 */
public class mask {
    public mask(string brand, string type) {
        this.brand = 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<mask> 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方法都会创建新的对象。

欢迎关注微信公众号:万猫学社,每周一分享java技术干货。

consumer接口

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

package java.util.function;

@functionalinterface
public interface consumer<t> {
    void accept(t t);
}

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

supplier<mask> supplier = () -> new mask("3m", "n95");
consumer<mask> 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

欢迎关注微信公众号:万猫学社,每周一分享java技术干货。

predicate接口

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

package java.util.function;

@functionalinterface
public interface predicate<t> {
    boolean test(t t);
}

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

supplier<mask> supplier = () -> new mask("3m", "n95");
predicate<mask> n95 = (mask mask) -> "n95".equals(mask.gettype());
predicate<mask> 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

欢迎关注微信公众号:万猫学社,每周一分享java技术干货。

function接口

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

package java.util.function;

@functionalinterface
public interface function<t, r> {
    r apply(t t);
}

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

supplier<mask> supplier = () -> new mask("3m", "n95");
function<mask, string> brand = (mask mask) -> mask.getbrand();
function<mask, string> 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

欢迎关注微信公众号:万猫学社,每周一分享java技术干货。

bifunction接口

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

package java.util.function;

@functionalinterface
public interface bifunction<t, u, r> {
    r apply(t t, u u);
}

我们可以用bifunction接口传入两个string直接创建mask实例:

bifunction<string,string,mask> 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

欢迎关注微信公众号:万猫学社,每周一分享java技术干货。

基本数据类型

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

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相关的接口

接口名称 方法名称 方法签名
supplier get () -> t
booleansupplier getasboolean () -> boolean
doublesupplier getasdouble () -> double
intsupplier getasint () -> int
longsupplier getaslong () -> long

consumer相关的接口

接口名称 方法名称 方法签名
consumer accept (t) -> void
doubleconsumer accept (double) -> void
intconsumer accept (int) -> void
longconsumer accept (long) -> void
objdoubleconsumer accept (t, double) -> void
objintconsumer accept (t, int) -> void
objlongconsumer accept (t, long) -> void

predicate相关的接口

接口名称 方法名称 方法签名
predicate test (t) -> boolean
bipredicate test (t, u) -> boolean
doublepredicate test (double) -> boolean
intpredicate test (int) -> boolean
longpredicate test (long) -> boolean

function相关的接口

接口名称 方法名称 方法签名
function apply (t) -> r
bifunction apply (t, u) -> r
doublefunction apply (double) -> r
doubletointfunction applyasint (double) -> int
doubletolongfunction applyaslong (double) -> long
intfunction apply (int) -> r
inttodoublefunction applyasdouble (int) -> double
inttolongfunction applyaslong (int) -> long
longfunction apply (long) -> r
longtodoublefunction applyasdouble (long) -> double
longtointfunction applyasint (long) -> int
todoublefunction applyasdouble (t) -> double
todoublebifunction applyasdouble (t, u) -> double
tointfunction applyasint (t) -> int
tointbifunction applyasint (t, u) -> int
tolongfunction applyaslong (t) -> long
tolongbifunction applyaslong (t, u) -> long

《死磕lambda表达式》系列

微信公众号:万猫学社

微信扫描二维码

获得更多java技术干货

死磕Lambda表达式(四):常用的函数式接口