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函数式接口 的相关文章

  • 如何将 JSpinner 的值设置为特定日期

    我有一个JSpinner我添加到JPanel我想将其时间设置为 GregorianCalendar calendar JSpinner spinner new JSpinner spinner setModel model pom add
  • 单元测试组合服务方法

    我正在为一个类编写 junit 单元测试 该类使用以下方法实现公开的接口 public Set
  • 如何在log4j的配置文件中为文件附加器提供环境变量路径

    我有一个log4j xml配置文件 和一个RollingFileAppender我需要提供用于存储日志的文件路径 问题是我的代码将作为可运行的 jar 部署在 Unix 机器上 所以如果我传递这样的参数 value logs message
  • GET 请求的 Spring 注解

    这两种spring GET方法有什么区别呢 哪一种是首选方法 Component Scope request Path public class TestComponent GET Path hello public String prin
  • 在 Java 中从 SOAPMessage 获取原始 XML

    我已经在 J AX WS 中设置了 SOAP WebServiceProvider 但我无法弄清楚如何从 SOAPMessage 或任何 Node 对象获取原始 XML 下面是我现在获得的代码示例 以及我试图获取 XML 的位置 WebSe
  • 检查 IPv4 地址是否在私有范围内

    在 Python 中 使用 IPy 模块您可以执行以下操作 gt gt gt ip iptype PRIVATE 有没有一个库或简单的方法可以在 Java 中执行相同的操作 似乎不完全是但是InetAddress有一些 isXX 方法 例如
  • Sorted(key=lambda: ...) 背后的语法[重复]

    这个问题在这里已经有答案了 我不太明白背后的语法sorted 争论 key lambda variable variable 0 Isn t lambda随意的 为什么是variable在看起来像的内容中陈述了两次dict 我认为这里的所有
  • Android WebView文件上传

    我正在开发一个 Android 应用程序 基本上它是一个WebView和一个进度条 Facebook 的移动网站 m facebook com 已加载到WebView 当我单击 选择文件 按钮上传图像时 没有任何反应 我已经尝试了所有的解决
  • 使用 JAX-WS 的 WebLogic 中没有模式导入的单个 WSDL

    如何使用 JAX WS 配置由 WebLogic 10 3 6 生成的 Web 服务 以将对象架构包含在单个 WSDL 文件声明 而不是导入声明 中 示例代码 界面 import javax ejb Local Local public i
  • 在 Java 中创建 T 的新实例

    在C 中 我们可以定义一个泛型class A
  • Java 中的 ExecuteUpdate sql 语句不起作用

    我正在学习如何将 SQL 与 Java 结合使用 我已成功安装 JDBC 驱动程序 并且能够从数据库读取记录并将其打印在屏幕上 我的问题发生在尝试执行更新或插入语句时 没有任何反应 这是我的代码 问题所在的方法 public static
  • 更改 JComboBox 中滚动条的大小

    有谁知道如何手动更改 jComboBox 中的滚动条大小 我已经尝试了一大堆东西 但没有任何效果 好吧 我明白了 您可以实现 PopUpMenuListener 并使用它 public void popupMenuWillBecomeVis
  • 如何在 Bean Validation 1.0 中构造 ConstraintViolationException?

    我对 javax validation API 感到困惑 我正在编写一个简单的测试来理解它 Sample sample new Sample Set
  • 改变 Java 中凯撒移位的方向

    用户可以通过选择 1 向左或 2 向右移动字母来选择向左或向右移动 左边工作正常 右边不行 现在它显示了完全相同的循环 但我已经改变了所有 and 以不同的方式进行标记 最终我总是得到奇怪的字符 如何让程序将字符向相反方向移动 如果用户输入
  • Jetty Plugin 9启动不喜欢icu4j-2.6.1.jar

    我对 mortbay 的 Maven jetty 插件 6 有相同的配置
  • java swing:向 JTree 项目添加自定义图形按钮

    我想在 JTree 中的项目右侧添加一个带有小图标的附加按钮 这可以做到吗 如果是这样 怎么办 thanks Clamp 你在这方面成功了吗 我想做同样的事情 但很难让 JButton 响应用户 设置渲染器以显示按钮的过程很顺利 但所有鼠标
  • 在循环中按名称访问变量

    我正在开发一个 Android 项目 并且有很多可绘制对象 这些绘图的名称都类似于icon 0 png icon 1 png icon 100 png 我想将这些可绘制对象的所有资源 ID 添加到整数 ArrayList 中 对于那些不了解
  • 使用 lambda 函数更改属性值

    我可以使用 lambda 函数循环遍历类对象列表并更改属性值 对于所有对象或满足特定条件的对象 吗 class Student object def init self name age self name name self age ag
  • Android Google 地图无法在当前主题中找到样式“mapViewStyle”

    添加谷歌地图视图时 我扩展了MapView 使用xml编辑器将其添加到活动中 并将我的谷歌地图api密钥手动添加到布局xml文件中 我的权限在清单文件中允许互联网 我想知道的是 在 xml 编辑器中 我收到错误 无法在当前主题中找到样式 m
  • 将数组值导出到 csv 文件 java

    我只需要帮助将数组元素导出到 csv 文件 我不知道我的代码有什么问题 任何帮助将不胜感激 谢谢 for int index 0 index lt cols length index FileWriter fw new FileWriter

随机推荐

  • 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表达式 只有确保接口当中在有且仅有一