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

在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表达式(四):常用的函数式接口的更多相关文章

  1. 死磕Lambda表达式(一):初识Lambda

    弱小和无知不是生存的障碍,傲慢才是.--<三体> 什么是Lambda表达式 Lambda表达式是表示可传递匿名函数的一种简洁方式,Lambda表达式没有名称,但是有参数列表.函数主体.返回 ...

  2. 死磕Lambda表达式(二):Lambda的使用

    城市就是森林,每一个男人都是猎手,每一个女人都是陷阱.--<三体> 在哪使用Lambda表达式? 在上一篇文章(传送门)中介绍了Lambda表达式的基本语法,其中的举了一个Lambda表达 ...

  3. 死磕Lambda表达式(三):更简洁的Lambda

    我们都是阴沟里的虫子,但总还是得有人仰望星空.--<三体> 在之前的文章中介绍了Lambda表达式的基本语法和正确使用姿势,这次我来介绍一些Lambda更简洁的用法. 欢迎关注微信公众号: ...

  4. 死磕Lambda表达式(五):Comparator复合

    给岁月以文明,而不是给文明以岁月.--<三体> 在上一篇文章(传送门)中介绍了JDK为我们提供的常用函数式接口,JDK不仅提供的这些函数式接口,其中一些接口还为我们提供了实用的默认方法,这 ...

  5. 死磕Lambda表达式(六):Consumer、Predicate、Function复合

    你的无畏来源于无知.--<三体> 在上一篇文章(传送门)中介绍了Comparator复合,这次我们来介绍一下其他的复合Lambda表达式. Consumer复合 Consumer接口中,有 ...

  6. Lambda01 编程范式、lambda表达式与匿名内部类、函数式接口、lambda表达式的写法

    1 编程范式 主要的编程范式有三种:命令式编程,声明式编程和函数式编程. 1.1 命令式编程 关注计算机执行的步骤,就是告诉计算机先做什么后做什么 1.2 声明式编程 表达程序的执行逻辑,就是告诉计算 ...

  7. 黑马Lambda表达式学习 Stream流 函数式接口 Lambda表达式 方法引用

  8. Java8新特性—四大内置函数式接口

    Java8新特性--四大内置函数式接口 预备知识 背景 Lambda 的设计者们为了让现有的功能与 Lambda 表达式良好兼容,考虑了很多方法,于是产生了函数接口这个概念. 什么是函数式接口? 函数 ...

  9. 常用的函数式接口Function接口和常用的函数式接口Function接口默认方法andThen

    常用的函数式接口Function接口 package com.yang.Test.FunctionStudy; import java.util.function.Function; /** * ja ...

随机推荐

  1. ES6的模块暴露与模块引入

    ES6的模块暴露和引入可以让我们实现模块化编程,以下列出ES6的几种模块暴露与引入的方式与区别. 1.ES6一共有三种模块暴露方法 多行暴露 模块1:module1.js //多行暴露 export ...

  2. 第一次安装vs2010无法运行程序,系统找不到exe文件,LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

    最近在看数据结构的一些书籍,怎奈代码是c写的,所以安装一个编译器vs2010来测试代码,但是建完文件后编译ok,f5却出现错误:无法启动程序,系统找不到指定文件.上网找了一些解决办法,但是仍然无法解决 ...

  3. Python---11模块

    在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很 ...

  4. 数据分析交互工具jupyter notebook需要密码登陆解决办法

    想要做数据分析,交互可视化工具jupyter notebook是必不可少的,但是在安装和使用其时候总是会出现各种各样的问题,本文针对notebook启动需要密码的问题进行解决. 首先看一下启动jupy ...

  5. Spring Boot 鉴权之—— JWT 鉴权

    第一:什么是JWT鉴权 1. JWT即JSON Web Tokens,是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519),他可以用来安全的传递信息,因为传递的信息是 ...

  6. API网关Kong

    官网:https://konghq.com/ 各种方式安装汇总:https://konghq.com/install/ 命令列表:https://docs.konghq.com/0.14.x/admi ...

  7. ES:在线迁移集群索引,数据不丢失

    一.背景 生产环境由于某些原因需要跨机房迁移ES集群,或者同机房原有集群中所有节点全部更换,期间ES索引要求完整,客户端请求中断不超过五分钟. 二.应用场景 1.同机房不同集群之间数据迁移: 2.跨机 ...

  8. 每天一个linux命令(15)-tail

    tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不断刷新, ...

  9. Android中JNI的使用方法(转载)

    Android中JNI的使用方法 首先看一下Android平台的框架图:(网上盗用) 可以看到Android上层的Application和ApplicationFramework都是使用Java编写, ...

  10. 微软发布MS MARCO数据集,提高计算机阅读理解能力

    ​ MARCO数据集,提高计算机阅读理解能力" title="微软发布MS MARCO数据集,提高计算机阅读理解能力"> ​ 本文译自:Microsoft data ...