Java函数式接口

2023-10-26

函数式接口

概念

  • 函数式接口在Java中指的是:有且仅有一个抽象方法的接口就称为函数式接口。
  • 函数式接口,适用于函数式编程,在Java中的函数式编程体现在Lambda,所以函数式接口就是用来服务Lambda表达式。只有确保接口当中在有且仅有一个抽象方法,Java中的Lambda才能顺利进行推导。

备注:“语法糖”是指使用更加便利方便,但是原理不变的代码语法。就比如遍历集合时使用foreach语法,其实底层使用的是迭代器,这便是“语法糖”。

格式
只要确保接口当中有且仅有一个抽象方法即可:

修饰符 interface InterfaceName{
	//只能定义一个抽象方法
	pubic abstract 返回值类型 方法名称(参数列表);
	//还可以定义其它非抽象方法
}

示例:

/*
    函数式接口:有且仅有一个抽象方法,一般作为方法的参数和返回值使用
    接口当中还可以包含其它方法(默认、静态、私有。。。)

 */
public interface Demo01 {
    void method();
}
//实现类
public class Demo01Impl implements Demo01{
    @Override
    public void method() {
        System.out.println("这是实现类重写的方法");
    }
    public static void show(Demo01 d){
        d.method();
    }
    
    public static void main(String[] args) {
        show(new Demo01Impl());
        show(new Demo01() {
            @Override
            public void method() {
                System.out.println("这是匿名内部类重写的方法");
            }
        });
        //Lambda
        show(()->{
            System.out.println("这是lambda表达式的写法");
        });
        //简化lambda
        show(()-> System.out.println("简化lambda"));
    }
}

@FunctionalInterface注解

Java 8中专门为函数式接口引入的一个新注解,该注解要定义在接口上。一旦在接口上定义该注释,编译器会强制检查该接口是否是不是一个函数式接口,该接口是否只有一个抽象方法,如果不是,编译出错

@FunctionalInterface
public interface interName{
	void method();
	//void show();
}

自定义函数式接口的用途

  • 对于自定义的函数式接口,一般用于方法的参数和返回值上。

函数式编程

能够在兼顾Java的面向对象特性的基础上,通过Lambda表达式与后面的方法引用,为开发者打开函数式编程的大门。

Lambda的延迟加载

有些场景的代码运行执行后,结果不一定会被使用到,从而造成性能的浪费。而lambda表达式是延迟执行的,正好可以解决此问题,提升性能。

使用Lambda作为方法的参数和返回值

  在Java当中,Lambda表达式是作为匿名内部类的替代品,如果一个方法的参数是一个函数式接口,那么可以使用Lambda表达式进行替代

public class Demo{
	public static void startThread(Runnable r){
		new Thread(r).start();
	}
public static void main(String[] args){
	startThread(()->{
		System.out.println("开启一个新线程,线程任务被执行了!");
	});
}
}

如果一个方法的返回值是一个函数式接口,那么我们可以直接使用一个lambda表达式。

代码如下:

public class Demo2{
	//定义一个方法,方法的返回值类型是一个函数式接口类型Comparator
	public static Comparator<String> createComparator(){
		//返回值就是一个函数式接口
		return new Comparator(){
			@Override
			public int compare(String o1,String o2){
				//自定义比较的规则  升序/降序
			}
		}
		//使用Lambda
		return(o1,o2) -> o1.length() - o2.length();
	}
	public static void main(String[] args){
		String[] strs={"aaa","a","bajdhj","dajdd"};
		Arrays.sort(strs,createComparator());
		System.out.println(Arrays.toString(strs));
	}
}

常用的函数式接口

 JDK提供了大量常用的函数式接口,丰富lambda表达式的使用场景,他们主要在java.util.functiion包中被提供。

Supplier接口

  • 该接口有且仅有一个无参的方法:T get()。用来获取一个泛型参数指定类型的对象数据。由于该接口是一个函数式接口,所以可以使用lambda表达式来操作它。
  • Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get()方法就会生产什么类型的数据。

代码如下:

 // 定义一个方法,方法的参数传递一个Supplier<T>接口,泛型指定String,get方法就会返回一个String
    public static String getString(Supplier<String> sup) {
        return sup.get();
    }
    // 定义一个方法,方法的参数传递一个Supplier<T>接口,泛型我指定为Integer,get方法就会返回一个int
    public static int getNum(Supplier<Integer> sup) {
        return sup.get();
    }
    public static void main(String[] args) {
        // 调用getString方法,方法的参数传递Supplier<T>是一个函数式接口,那么我们就可以使用Lambda
       /*  String str = getString(() -> {
            // 生产一个字符串并返回
            return "你好Java";
        });
        System.out.println(str);*/
        
        // 求一个int类型的数组中的最值
        int[] arr = {10,20,5,8,3,50};
        int maxNum = getNum(() -> {
            // 求出数组的最大值
            int max = arr[0];
            for (int i : arr) {
                // 判断
                if (max < i) {
                    max = i;
                }
            }
            return max;
        });
        // 输出最大值
        System.out.println(maxNum);// 50
    }

Consumer 接口

java.util.function.Consumer<T>接口刚好和Supplier接口相反,它不是用来生产一个数据,而是消费一个数据。

accept方法

意思就是消费一个指定泛型的数据。

代码如下:

   // 定义一个方法,方法的参数传递一个Consumer<String>接口,传递一个字符串变量
    public static void consumer(String str, Consumer<String> con) {
        // 使用消费型接口对象,消费传递的字符串值。
         con.accept(str);
    }

    public static void main(String[] args) {
        // 来调用消费方法consumer,Consumer<String>接口是一个函数式接口类型,所以可以使用Lambda表达式
        consumer("abcdefg", name -> {
            // 把里面的abcdefg字符串改为大写输出 消费的规则自定义
            String str = name.toUpperCase();
            String s = new StringBuffer(str).reverse().toString();
            System.out.println(s);// GFEDCBA
        });
    }  
默认的方法:andThen

如果一个方法的参数和返回值全都是Consumer类型,那么就可以实现这样的效果:消费数据的时候,首先做一个消费的操作,在做一个消费的操作,实现组合。可以通过Consumer接口当中的默认方法:andThen来实现。

代码如下:

// 定义一个方法,方法的参数传递一个字符串和两个Consumer接口,Consumer接口的泛型指定为字符串
    public static void consumers(String str, Consumer<String> con1,Consumer<String> con2) {
       /* con1.accept(str);
        con2.accept(str);*/
        // andThen 连续消费  default Consumer<String> andThen
        // 先执行左边的Consumer--con1的动作,andThen--->再次执行Consumer--con2动作
        con1.andThen(con2).accept(str);
        // 规则 con1连接con2 ,先执行con1消费数据,在执行con2消费数据
    }

    public static void main(String[] args) {
        // 由于consumers方法的参数Consumer接口是一个函数式接口,可以使用Lambda表达式
        consumers("Java31-中国最棒-都是业界大佬", (name1)->{
              // 消费规则
              // 截取传入的字符串
            String sub = name1.substring(0, 6);
            System.out.println(sub);

        }, (name2) -> {
            // 定义消费的规则 分成字符串数组展示
            String[] strs = name2.split("-");

            System.out.println(Arrays.toString(strs));// {“Java31","中国最棒","都是业界大佬"}
        });
    }

通过查看源码得知:andThen方法不允许传入一个null对象否则就会抛出空指针异常。

要想把两次消费的动作连接起来,需要传入两个Consumer接口,通过andThen方法实现一步一步执行消费动作。

练习:

​ 定义一个字符串数组,存储每一个人的信息如:“张三,20,郑州市”,存储5个人的信息

​ 使用Consumer接口,按照指定的格式进行打印输出:姓名:张三;年龄:20;地址:郑州市

​ 要求将打印姓名的动作作为第一个Consumer接口的规则

​ 将打印年龄的动作作为第二个Consumer接口的规则

​ 将打印地址的动作作为第三个Consumer接口的规则。

​ 最终将三个Consumer接口按照规定的顺序拼接输出出来。

​ 代码如下:

  // 规则
    public static void consumers(String[] arr, Consumer<String> con1, Consumer<String> con2, Consumer<String> con3) {
        // 操作arr数组当中的每一个元素
        for (String str : arr) {
            con1.andThen(con2).andThen(con3).accept(str);// 定义了消费的先后的顺序
        }
    }
    public static void main(String[] args) {
        // 定义一个字符串数组
        String[] arr = {"李四,20,南阳市", "张三,20,郑州市", "小孙,20,开封市", "小丽,20,信阳市", "小赵,20,洛阳市"};
        // 调用consumers方法,由于Consumer接口是一个函数式接口,所以可以使用Lambda
        consumers(arr, one -> System.out.print("姓名:" + one.split(",")[0] + ";"),
                two -> System.out.print("年龄:" + two.split(",")[1] + ";"),
                three -> System.out.println("地址:" + three.split(",")[2]));

    }  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java函数式接口 的相关文章

  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 如何使用 LAMBDA 表达式在 LINQ 中执行 IN 或 CONTAINS?

    我有以下 Transact Sql 我正在尝试将其转换为 LINQ 并且很挣扎 SELECT FROM Project WHERE Project ProjectId IN SELECT ProjectId FROM ProjectMemb
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo

随机推荐

  • sql2005 查看数据库或表大小的系统存储过程 sp_spaceused

    sql2005 查看数据库或表大小的系统存储过程 sp spaceused 语法 sp spaceused objname objname updateusage updateusage 参数 objname objname 请求其空间使用
  • 开机后电脑只剩计算机和回收站,电脑开机后C盘拒绝访问,图标只剩下此电脑和回收站是怎么回事?...

    它既然提示我们C WINDOWS system32 config systemprofile Desktop这个目录的桌面不可用 那么我们可以通过复制 桌面 文件夹到子文件里面来解决 首先我们要先找到自己当前用户名下的 桌面 后才可以复制
  • 【BP数据预测】粒子群算法优化BP神经网络数据预测(多输入多输出)【含Matlab源码 1418期】

    一 粒子群算法及BP神经网络简介 由于BP神经网络在应用过程中初始权值和阈值随机选取 容易出现局部收敛极小点 从而降低拟合效果 为了解决这个问题 采用PSO优化BP神经网络 PSO BP 算法的初始权值和阈值 解决局部极小点问题 提高BP神
  • es 时间字段聚合_es Elasticsearch 时间分组聚合查询

    正常业务逻辑中 会出现大量的数据统计 比如说分组聚合查询 根据天进行数据的统计 记录下es分组聚合查询 size 0 aggs groupDate date histogram field create date interval day
  • 剑指Offer - 面试题11:旋转数组的最小数字

    题目 把一个数组最开始的若干个元素搬到数组末尾 我们称之为数组的旋转 输入一个递增排序的数组的一个旋转 输出旋转数组的最小元素 例如 数组 3 4 5 1 2 为 1 2 3 4 5 的一个旋转 该数组的最小值为1 分析 暴力法 我们不考虑
  • 逻辑分析仪

    1 常见逻辑分析仪使用视频 什么是逻辑分析仪 逻辑分析仪和示波器的区别 B站视频 Kingst逻辑分析仪快速上手 哔哩哔哩 bilibili 泰克 安捷伦已经是老品牌了 ZLG致远电子 金思特 青岛 逻辑分析仪 价格 图片 品牌 怎么样 京
  • 使用LVM对服务器磁盘进行扩容

    使用LVM进行磁盘扩容 文章目录 使用LVM进行磁盘扩容 1 在虚拟机目录添加磁盘 2 lsblk查看系统的磁盘情况 3 硬盘分区 4 创建物理卷 5 将新的分区 dev sdb1加入到卷组中 这里的卷组名为klas 6 扩容已有分区 1
  • 恶意代码分析实战 2 动态分析基础技术

    2 1 Lab3 1 使用动态分析基础技术来分析在Lab03 01 exe文件中发现的恶意代码 问题 找出这个恶意代码的导入函数与字符串列表 C Documents and Settings Administrator gt strings
  • Appium模拟坐标点击

    这种方法在 元素定位不到时 可以尝试一下 方法 tap self positions duration None Args positions list类型 里面对象是元组 最多五个 如 100 20 100 60 duration 持续时
  • idea git版本回退

    文章目录 idea git版本回退 前言 步骤 具体操作 第一步 查看old的版本号 第二步 本地代码 Reset Head old的版本号 第三步 强制push到远程仓库 idea git版本回退 前言 由于我错误的push了一些代码 想
  • WDK学习笔记_Kaggle_Transformer_docker

    文章目录 摘要 一 深度学习 Kaggle竞赛 1 1 model的选择 1 2 常用包 1 3 解决问题流程 1 3 1 认知数据 二 文献 Transformer 2 1 摘要 2 2 介绍 2 3 Transformer架构 2 3
  • [数据库与软件工程]一、关系数据库的结构(表、元组、属性、关系等)

    目录 一 前言 二 主要内容 1 认识表 列首 表 列首 2 一些关系模型术语 元组 tuple 属性 attribute 关系 relation 关系实例 relation instance 域 domain 空值 null 一 前言 这
  • 【PPT插件】图表和布局软件 think-cell 12 新版发布

    think cell 12 版本中包含的增强功能会提高您轻松控制 连接和显示更多信息的能力 从向多个分区 而不是只有一侧 应用颜色 到在 Excel 中将 Harvey ball 复选框甚至图像链接到数据 think cell 继续为您日复
  • 最大公约数和最小公倍数的关系

    联系 最大公约数 指两个或多个整数共有的约数中最大的那个 最小公倍数 指两个或多个整数共有的倍数中最小的那个 以两个整数为例 最大公约数表示为 a b 最小公倍数表示为 a b 定理 a b X a b ab a b均为整数 例题 incl
  • 高效程序员工作法(五)

    前言 本篇博客内容来源自 极客时间课程 10x程序员工作法 处于学习记录 将个人认为比较重要的知识点进行摘抄记录 有兴趣的同学去极客时间学习完整课程 10x程序员工作法 开发效率 10倍效率 极客时间 一 为什么世界和你理解的不一样 我们努
  • 优雅地处理RabbitMQ中的消息丢失

    目录 一 异常处理 二 消息重试机制 三 错误日志记录 四 死信队列 五 监控与告警 优雅地处理RabbitMQ中的消息丢失对于构建可靠的消息系统至关重要 下面将介绍一些优雅处理消息丢失的方案 包括异常处理 重试机制 错误日志记录 死信队列
  • 【数据库(三)】DML和DDL的学习

    文章目录 1 DML语言 1 1 插入 方式一 最常用 方式二 两种方式PK 1 2 修改 修改单表语法 修改多表语法 1 3 删除 方式1 delete语句 方式2 truncate语句 两种方式的区别 面试题 2 DDL语句 2 1 库
  • 改进的多目标差分进化算法在电力系统环境经济调度中的应用(Python代码实现)【电气期刊论文复现】

    欢迎您的到来 博客主页 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 床头铭 将来的我一定会感谢现在奋斗的自己 专栏目录链接 电气代码 智能算法及其应用 路径规划 神经网络预测 优化调度 图像处理 车间调度 信号处理 浪漫的她 我的哲思
  • OpenGL入门教程之 纹理

    引言 我们已经了解到 我们可以为每个顶点添加颜色来增加图形的细节 从而创建出有趣的图像 但是 如果想让图形看起来更真实 我们就必须有足够多的顶点 从而指定足够多的颜色 这将会产生很多额外开销 因为每个模型都会需求更多的顶点 每个顶点又需求一
  • Java函数式接口

    函数式接口 概念 函数式接口在Java中指的是 有且仅有一个抽象方法的接口就称为函数式接口 函数式接口 适用于函数式编程 在Java中的函数式编程体现在Lambda 所以函数式接口就是用来服务Lambda表达式 只有确保接口当中在有且仅有一