JDK8新特性--函数式接口--(Consumer的概念理解,模拟练习,企业实战)全流程彻底搞懂

背景,起因是因为在项目开发过程中,发现了一处代码的写法觉得很新奇看不懂,了解后发现是用到了函数式接口的知识。特此学习记录,整体过程梳理在本文。如果你不满足就会写个CURD,业务代码只会new来new去,代码维护性差,本文可以给你提供思路,告诉你写出一个巨屌的代码,同样的逻辑,不同的写法,其他程序员一眼看的哇塞和懵逼。

1 本人对【函数式接口】的理解

  • 为什么以前没听说过这个东西?

答:JDK8新特性,Java提出了函数式接口。

  • 为什么要使用函数式接口?

使用函数式接口,提高了代码的灵活性,后面的案例会带你体验有多吊,吊打你以前的写法

  • 什么是函数式接口?

接下来会从两个维度解释。

维度一:资料定义
在这里插入图片描述

希望第一步你能够看懂这个解释,能看懂 【匿名内部类】和【lambda表达式】写法
若果这一步吃力的话,可以参考这篇文章,写的很基础和全面,通俗易懂
点击查看-> 匿名内部类、Lambda、方法引用 的总结


维度二:JDK提供的函数式接口

对于新手的我们,使用函数式接口,基本上就是使用JDK提供的大量函数式接口。不同场景下使用不同的函数式接口,现在还没能力去自定义一个函数式接口,让项目代码有优雅。

在搜索资料的过程中,了解到了一个新名词:Java语法糖
(为了不影响本文梳理逻辑,关于语法糖的介绍我放到了章节,右侧目录可以查看)

这里作者想要强调的是,使用JDK提供的函数式接口,让我们代码更优雅了,某种程度上符合
Java语法糖的思想。理解这一点,也就能更透彻的理解函数式接口这个设计的优点。

好了,回到正题

  • JDK提供了哪些函数式接口呢?
    在这里插入图片描述
    在这里插入图片描述
    本文介绍的是java.util.function包下的接口,其中核心的有
  • Supplier接口
  • Consumer接口
  • Predicate接口
  • Function接口
  • 等等

下面会介绍 Consumer接口使用案例

2 函数式接口–>Consumer接口案例

现在有一个需求:创建一个list列表,存储数据,直接打印列表的内容

@Test
public void demo(){List<String> list = Arrays.asList("John","Andy");printList(list);
}public void printList(List<String> list){for(String s : list){System.out.println(s);}
}

现在我们的代码很优雅,客户需要打印功能,只需要调用printList方法就行,完全不需要操心如何实现的

现在客户需求变了:创建一个list列表,存储数据,将大写转化为小写后再打印列表的内容

@Test
public void demo(){List<String> list = Arrays.asList("John","Andy");printList(list);
}public void printList(List<String> list){for(String s : list){//变动的地方System.out.println(s.toLowerCase);}
}

按照客户需求,只需要修改一次printList方法的内容就行了。完美解决

现在需求又又变了:创建一个list列表,存储数据,将小写转化为大写后再打印列表的内容

@Test
public void demo(){List<String> list = Arrays.asList("John","Andy");printList(list);
}public void printList(List<String> list){for(String s : list){//变动的地方System.out.println(s.toUpperCase);}
}

再次按照客户需求,第二次修改printList方法的内容。完美解决

现在需求又又又又又变了…,是不是每次变动,都需要修改printList方法内容,这也太麻烦了。我打算把控制权给客户,需要什么自己去修改,不要动我 printList()方法的代码了。

如何实现呢,借用函数式接口Consumer

@Test
public void demo(){List<String> list = Arrays.asList("John","Andy");printList(list, new Consumer<String>() {@Overridepublic void accpet(String s){System.out.println(s);//System.out.println(s.toLowerCase);//System.out.println(s.toUpperCase);}}
}public void printList(List<String> list,Consumer<String> consumer){for(String s : list){consumer.accept(s);}
}

这里使用了匿名内部类的写法,实际上不这样写,而是使用lambda表达式,优化后的代码

@Test
public void demo(){List<String> list = Arrays.asList("John","Andy");printList(list, s-> System.out.println(s));}
}public void printList(List<String> list,Consumer<String> consumer){for(String s : list){consumer.accept(s);}
}

分析一下,当程序运行后,开始调用printList方法,进入printList方法后,执行for循环,每次遍历都要执行accept方法,accept方法被重写了,就执行重写的内容。

当然了,看到这里你肯定会心有疑惑:我就是想要遍历+打印而已,怎么弄得这么复杂,还不如直接全写在demo()里面,使用最原始的方式。

这么想就错了,企业的项目是很复杂的,不是本案例演示的这些功能。

3 项目使用的案例

我现在得到一个json格式的字符串,需要将其解析后存到list中,得到list的长度,如果长度大于2,打印:我是2,否则打印:我是其他

3.1 普通写法

文件A
public class JsonUtils {public int parseJsonString(String jsonString) {JSONArray jsonArray = JSON.parseArray(jsonString);List<Person> personList = jsonArray.toJavaList(Person.class);int length = personList.size();return length;}
}
文件B
public class Example {public static void main(String[] args) {String jsonString = "[{\"name\":\"Alice\", \"age\":25}, {\"name\":\"Bob\", \"age\":30}]";int length = JsonUtils.parseJsonString(jsonString);printResult(length);}private static void printResult(int length) {if (length > 2) {System.out.println("我是2");} else {System.out.println("我是0");}}
}

这种普通写法是我们大家最习惯的写法,阅读起来完全没有问题。
注意分析主函数:我们一共传递了两次参数
在这里插入图片描述

那么接下来我们尝试修改为函数式接口的写法

3.2 lambda+函数式接口写法

看不懂代码,先看本章节后面结论

文件A
public class JsonUtils {public static void parseJsonString(String jsonString, Consumer<Integer> consumer) {JSONArray jsonArray = JSON.parseArray(jsonString);List<Person> personList = jsonArray.toJavaList(Person.class);int length = personList.size();consumer.accept(length);}
}
文件Bpublic class Example {public static void main(String[] args) {String jsonString = "[{\"name\":\"Alice\", \"age\":25}, {\"name\":\"Bob\", \"age\":30}]";Consumer<Integer> consumer = length -> {if (length > 2) {System.out.println("我是2");} else {System.out.println("我是其他");}};//将该Lambda表达式传递给JsonUtils类的parseJsonString方法,以执行解析JSON字符串、获取列表长度并打印结果信息的操作。JsonUtils.parseJsonString(jsonString, consumer);}
}

看看能否理解此代码?
在这里插入图片描述
可以看到此部分的代码使用了函数式接口+lambda表达式,希望大家先知道如何写这种风格的代码,作者知道大家一定一定会非常疑惑,改造后的代码怎么感觉更乱了,一点没看出来哪里优雅,总不能说使用了函数式接口就优雅。
注意看,粗看感觉很乱,仔细分析主函数内容:
在这里插入图片描述

可以发现,我们这次只传递了一次参数。只不过lambda表达式那一坨看着很恶心,不美观。要是能抽离出去,成为一个单独的方法就好了

3.3 方法引用+函数式接口写法

A 文件public class JsonUtils {public static void parseJsonString(String jsonString, Consumer<Integer> consumer) {JSONArray jsonArray = JSON.parseArray(jsonString);List<Person> personList = jsonArray.toJavaList(Person.class);int length = personList.size();consumer.accept(length);}
}
B 文件public class Example {public static void main(String[] args) {String jsonString = "[{\"name\":\"Alice\", \"age\":25}, {\"name\":\"Bob\", \"age\":30}]";Consumer<Integer> consumer = Example::printResult;JsonUtils.parseJsonString(jsonString, consumer);}private static void printResult(int length) {if (length > 2) {System.out.println("我是2");} else {System.out.println("我是其他");}}
}

这种写法简直太完美:传递一次参数,代码简洁。

4 总结

总结一下:

在这里插入图片描述
这里作者可以再具体说说有什么好处。

原客户需求:我现在得到一个json格式的字符串,需要将其解析后存到list中,得到list的长度,如果长度大于2,打印:我是2,否则打印:我是其他

现在客户需求变了,且需要你的同事负责开发:

  • 我现在得到一个json格式的字符串,需要将其解析后存到list中,得到list的长度,

  • 如果长度小于2,打印:我比2小;

  • 长度等于2,打印:我是2;

  • 长度大于2,打印:我比2大

如果你按照最初代码版本写的
你的同事:需求修改printResult()方法内容,然后在主函数进行测试:调用parseJsonString()方法获取返回值,将返回值传递给printResult()方法

如果你按照最初代码版本写的
你的同事:需求修改printResult()方法内容,然后在主函数进行测试:不需要改动代码

神奇吧,神奇吧,就是这么玩的。第一次写完后,以后的程序员不需要关心调用了什么方法,传递了什么参数,他需要做的仅仅就是修改业务代码printResult()。这代码质量太高了。拓展性,封装性,维护性都考虑到了。

5 我的企业代码实战案例

文件A.java@Overridepublic void afterPropertiesSet() throws Exception {SyslogDataSyncConsumer<String, String> consumer = new SyslogDataSyncConsumer<String, String>;Integer syncCount = consumer.consumerInfo(Collections.singletonList(KafkaTopicConst.Event_BMS_SYSLOG_ROLE),consumer::handle);}public void handle(ConsumerRecords<String, String> records) {........(业务功能处理)    }      
文件B.javapublic Integer consumerInfo(List<String> topics,Consumer<ConsumerRecords<K, V>> recordsHandler){// 拉取超时毫秒数,如果没有新的消息可供拉取,consumer会等待指定的毫秒数,到达超时时间后会直接返回一个空的结果集ConsumerRecords<K, V> records = null;....//省略详细处理recods过程....//kafka消息处理器处理读取到的消息recordsHandler.accept(records);}

能看懂此代码吗?
内部的原理就是图示的流程
这里解释一下,

5 语法糖

在这里插入图片描述
通俗点解释,我们在写代码的时候,需要尽量争取让我们的代码更优雅,更容易理解。
比如正常遍历数组arrayTest

for(int i = 0; i < arrayTest.seize(); i++){Sysytem.out.println(arrayTest[i]);
}

JDK1.5版本后,支持使用增强for循环写法

for (String s : arrayTest) {Sysytem.out.println(s);     
}

可以看到这种效果是不是更优雅,更不容易出错(不用担心循环次数,数组下标是否正确)

还有哪些地方用到了语法糖,参考本文链接---->[点击查看]

10 JDK8的新特性有哪些

点击查看–> JDK8的新特性参考文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/131343.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件工程评级B-,有大量调剂名额。北京联合大学考情分析

北京联合大学(B-) 考研难度&#xff08;☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1239字&#xff0c;预计阅读&#xff1a;3分钟 2023考情概况 北京…

从零开始-与大语言模型对话学技术-gradio篇(4)

前言 本文介绍「星火杯」认知大模型场景创新赛中的落选项目- AI命理分析系统&#xff0c;属于个人娱乐练手。总结提炼了往期文章精华并发掘出新的知识。 包括本地部署版本和Web在线版本&#xff0c;两种打包方式基于 半自动化使用.bat手动打包迁移python项目 如何把 Gradio …

Java——》synchronized互斥性

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

你应该知道的几个国产化平台-行云管家

近年来我国国产化加速发展&#xff0c;国产化平台也越来越多。但还有很多小伙伴不知道有哪些&#xff0c;这里就给大家汇总几个&#xff0c;大家应该知道的国产化平台。 你应该知道的几个国产化平台 1、cpu&#xff1a;龙芯、飞腾、鲲鹏、兆芯、海光、申威 2、浏览器&#xf…

Vercel的下一件大事:AI SDK和开发人员加速器

Vercel CEO Guillermo Rauch说&#xff0c;构建AI应用程序是开发人员注册Vercel的第二大原因。Ergo&#xff1a;Vercel AI SDK和加速器。 在 2020 年代&#xff0c;很少有公司比流行的 React 框架 Next.js 的管理者 Vercel 对前端开发人员生态系统产生更大的影响。当我在 2020…

骨传导耳机怎么听到声音?骨传导耳机是否会对听力造成损害?

其实骨传导耳机让我们听到的的传声原理很简单&#xff0c;而且骨传导现象很常见&#xff0c;简单的来说&#xff0c;就是像我们平时吃薯片或者挠头发&#xff0c;无论声音再小&#xff0c;自己也能听见&#xff0c;这就是骨传导的现象&#xff0c;也是为啥骨传导耳机不需要入耳…

GitHubGiteeGitlab极狐(JihuLab)同时生成并配置SSH公私钥详细过程

GitHub-微软-github.com Gitee-开源中国- gitee.com Gitlab-乌克兰GitLab 公司-gitlab.com 极狐(JihuLab)-中国代理商运营的Gitlab -gitlab.cn或者jihulab.com 使用SSH公钥可以让你在你的电脑和GitHub等平台通讯的时候使用更安全的连接&#xff08;Git的Remote要使用SSH地址&a…

计算机竞赛 大数据疫情分析及可视化系统

文章目录 0 前言2 开发简介3 数据集4 实现技术4.1 系统架构4.2 开发环境4.3 疫情地图4.3.1 填充图(Choropleth maps)4.3.2 气泡图 4.4 全国疫情实时追踪4.6 其他页面 5 关键代码最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 大数据疫…

vue应用全局音乐(自动播放)

这里写自定义目录标题 1.从同事哪里白嫖过来的&#xff0c;主要是jq写的&#xff0c;需要单独引入jq cdn 2.打开index.html 将代码放到里面 <!DOCTYPE html> <html><head><meta charset"utf-8" /><metaname"viewport"content…

软件设计——面向对象的七大原则

前言 软件设计模式和设计原则是成为一个软件架构师的基本功&#xff0c;较好的理解这些基础知识无疑是十分重要的。在这篇文章中荔枝将会比较详细梳理一下面向对象的七大原则&#xff0c;大家可以先看看这部分内容再去学习设计模式会比较好哈哈哈哈~~~ 在软件开发中&#xff0c…

Linux RPM JDK升级

以JDK1.8升级JDK17为例 上传jdk17安装包到linux服务器 检查jdk版本 rpm -qa|grep jdk 删除查询到的jdk rpm -e --nodeps jdk1.8-1.8.0_201-fcs.x86_64 删除完毕后安装新的jdk rpm -ivh jdk-17_linux-x64_bin.rpm 检查jdk版本 java -version

深入探讨基于python的SGBM参数影响效果

什么是SGBM SGBM&#xff08;Semi-Global Block Matching&#xff09;是一种用于计算双目视觉中视差&#xff08;disparity&#xff09;的半全局匹配算法&#xff0c;在OpenCV中的实现为semi-global block matching&#xff08;SGBM&#xff09;。它是基于全局匹配算法和局部匹…

Matlab 2016安装MinGW-w64-4.9.2

Matlab 2016安装MinGW-w64-4.9.2 项目需求&#xff1a;需要将matlab中的.m文件编译为cpp文件 .dll .h .lib。 我相信大家在对matlab2016安装MinGW-w64出现了各种各样的问题。如&#xff1a;4.9.2安装失败&#xff1b;安装了其他版本但是matlab检测不到&#xff0c;或者其他各种…

Matlab之DICOM(数字图像和通信医学)格式图像数据读取函数dicomread

一、DICOM是什么&#xff1f; DICOM是数字图像和通信医学格式的图像数据&#xff0c;在MATLAB中&#xff0c;可以使用dicomread函数读取DICOM格式的图像数据。 二、dicomread函数 使用方法如下&#xff1a; imageData dicomread(filename);其中&#xff0c;filename表示DI…

pdfjs解决ie浏览器预览pdf问题

pdfjs是一个js库&#xff0c;可以将pdf文件用canvas重新绘制&#xff0c;从而无需借助pdf读取插件就可以直接预览。 目前chrome内核的浏览器已内置pdf读取插件&#xff0c;但ie浏览器还没有。而我们最近在做的一个项目使用对象是医院&#xff0c;使用的浏览器竟然还是ie。所以我…

基础秘钥、公钥、地址的熟悉指南

1. 地址 0基础漫画式阅读&#xff1a;https://www.cnblogs.com/charlesblc/p/6130433.html 清晰详细的地址生成解释&#xff1a;比特币&#xff1a;账户私钥、公钥、地址的生成 - kumata - 博客园 (cnblogs.com) 对原理更详细解释&#xff1a;区块链技术核心篇之二&#xff…

在微信小程序上怎么实现多门店管理功能

微信小程序已经成为连接线上与线下的重要工具&#xff0c;尤其对于拥有多家门店的企业来说&#xff0c;通过微信小程序可以实现多门店管理&#xff0c;提高管理效率和用户体验。下面&#xff0c;我将为大家详细介绍如何在微信小程序上实现多门店管理功能。 一、确定多门店管理功…

【网络教程】记一次使用Docker手动搭建BT宝塔面板的全过程(包含问题解决如:宝塔面板无法开启防火墙,ssh,nginx等)

文章目录 准备安装安装宝塔面板开启ssh和修改ssh的密码导出镜像问题解决宝塔面板无法开启防火墙无法启动ssh设置密码nginx安装失败设置开机启动相关服务准备 演示的系统环境:Ubuntu 22.04.3 LTS更新安装/升级docker到最新版本升级docker相关命令如下# 更新软件包列表并自动升级…

没有软件怎么管理固定资产

在当今数字化的世界中&#xff0c;我们已经习惯了使用各种软件来管理我们的日常生活和工作。然而&#xff0c;当我们面临一个看似简单的问题——如何管理固定资产时&#xff0c;我们可能会感到困惑。那么&#xff0c;如果没有软件&#xff0c;我们该如何进行资产管理呢&#xf…

文章生成器免费版

你是否曾经陷入文案创作的困扰中&#xff1f;是不是为了撰写出优质的文章而煞费苦心&#xff1f;那么&#xff0c;如果我告诉你&#xff0c;现在有一种神奇的工具&#xff0c;可以为你解决这个问题&#xff0c;让你轻松地生成文章&#xff0c;你会不会感到兴奋呢&#xff1f;让…