Java8函数式编程实践精华

Java 函数式编程最佳实践 通过使用 Lambda 表达式、方法引用、函数式接口、避免改变状态和副作用,以及并行流进行并行计算,我们可以写出更简洁、可读性更高且具有良好可维护性的代码。函数式编程的特性和工具为我们解决问题提供了强大的工具,我们应该充分利用它们来提高我们的开发效率和代码质量。Java 8 引入了函数式编程的概念,并提供了许多函数式编程的特性和工具。在函数式编程中,函数应该是无状态的,不依赖于外部状态,并且不改变传入的参数或全局状态。在函数式编程中,使用并行流可以有效地进行并行计算,提高程序的性能。方法计算所有整数的和。 阅读详情

绪论

从java8开始,我们就可以通过java8中的StrameAPI与Lambda表达式实现函数式编程,可以让代码变得更加高效简洁。现在很多企业的生产代码已经开始使用java8了,对于还没有使用过java8进行的编程的朋友们可以好好的学习一下,我在企业中写java8也有一段时间了,我想把我在实际开发中用到的一些场景与大家分享一下,大部分例子都来源于我开发项目中的实例。其中我开发中用得比较多的是,Optional,SteameAPI与lambda。本文是实战帖,不做过多理论分析,直接讲场景与应用。Java9已经出来一段时间了,我发现我周围的很多做开发的朋友对java8中的一些新特性仍然不是很了解,也没在生产代码中使用过java8,不过我相信,很快,大部分公司都会用上java8的,我觉得java8与java5一样,是jdk历史上重要的一个版本更新,能给java编程带来巨大变化的一个版本。

场景

1.数据类型转换

直接上代码

//拿到所有的processNumber
List<String> processNumbers = param.getListProcessNumbers().stream().
map(QueryStateData::getProcessNumber).collect(Collectors.toList());

上面的代码的作用中把List<Object>,把其中我们需要的一个string字段变成List<String>,map是StringAPI中用来做数据类型转换的,QueryStateData::getProcessNumber是方法引用,作用与object->object.getProcessNumber();一样,collect是收集器,通过收集器,把流转换成我们想要的List<String>。

2.对List数据进行数据筛选

//获取paymentChange
Optional<GaPaymentChange> changeOptional = listPaymentChange.stream().filter(p -> p.getTransferNo().equals(std.getProcessNumber())).findFirst();
if(changeOptional.isPresent()){
	GaPaymentChange paymentChange = changeOptional.get();
}

filter从名字上看,就知道是用来过数据过滤的,filter的函数式接口中需返回一个boolean值。findFirst是取其中的第一个,可以返回一个Optional对象。通过get方法我们很轻松的拿到了我们想要的结果。

3.Optional对象的应用

java8中Optional的出现是为了减少空指针异常的。看代码应用:

BigDecimal bigAbmout = Optional.ofNullable(paymentChange.getPaymentChangeMoney()).orElseGet(() -> new BigDecimal("0")).setScale(2, BigDecimal.ROUND_HALF_UP);

当ofNullable值为null时,我们可以给bigAbmout赋一个默认值。orElseGet的传参数是一个函数式接口,上面代码可以把它写成
lambda要返回一个对象。

Optional.ofNullable(paymentChange.getPaymentChangeMoney()).orElse(new BigDecimal("0")).setScale(2, BigDecimal.ROUND_HALF_UP);

orElse与orElseGet不同的是,它的参数直接是目标对象。

4.StreamAPI遍历对象

page.getRows().stream().forEach(x -> x.setOrderTime((DateUtils.dateFormat(x.getCreateTime(),DateUtils.DAT_SHORT_FORMATSS))));

上面的代码就是简单的把集合对象中orderTime的值做一下转换。

5.快速找到集合中想要匹配数据

//是否存在增补单
boolean match = gaPaymentChangeDetailList.stream().anyMatch(detail -> GaConstants.SUPPLEMENT_BILL.equals(detail.getIsSupplementBill()));
            

anyMatch配合lambda表达式可以在集合中快速找到我们想匹配的数据。

6.List中对象转换

List<Menu>menus= menuService.queryMenuList(query);List<MenuTreeVO> menuTrees = menus.stream().map(MenuTreeVO::new).collect(Collectors.toList());

利用StreamAPI两行代码就把List<Menu>转成了 List<MenuTreeVO>,其中的map(MenuTreeVO::new)等价于map(menu->new MenuTreeVO(menu)),所以,实现的一个另一个细节,我重写了MenuTreeVO的构造方法:

public MenuTreeVO(Menu menu) {
	this.id = menu.getId();
	this.pId = menu.getParentId();
	this.name = menu.getName();
	this.open = true;
}

7.枚举中的应用

枚举中我们通常会与一个静态方法通过code去获取它对应的枚举,没有用java8我们一般是通过for循环实现的,看看java8代码:

/**
 * 获取枚举
 * 
 * @param code
 * @return
 */
public static OrderStateEnum getEnum(Integer code) {
	return Stream.of(OrderStateEnum.values()).filter(e ->e.code.equals(code)).findFirst().orElse(null);
}

8.lambda实现函数式接口

我们原来代码中的遇到的函数式接口,我们就可以用lambda来代替,简单的来说,就是new接口的地方。比如MQ发消息,我们传统的做法:

jmsTemplate.send(new MessageCreator() {
	@Override
	public Message createMessage(Session session) throws JMSException {
		return session.createTextMessage(String.valueOf(id));
	}
});

这个函数式接口可以用lambda一行代码轻松实现:

jmsTemplate.send(session -> session.createTextMessage(String.valueOf(id)));

8.去重、求和、最大值、最小值

用法都比较类似,这里就不一一列举了。下面看一个去重的。stream下面的方法也就那么多个,要用的时候可以一个个点来看看,从英文意思我们可大概知道那些方法基本上用来做什么的了。其实很多用法我也是在实际开发中慢慢研究出来的,也没看很多的资源。

List<Color> colors = skusResult.getValue().stream().map(Sku::getColor).distinct().collect(Collectors.toList());

上面是对List<Color>中的Color对象去重,记得重写hashCode()与equeals()方法。

9.对List统计出现次数,按出现次数排序

这个用法也是实际生产中用到的,直接上代码。

//此处是java9之后的快速创建list的写法
var names = List.of("aaa", "aaa", "aaa", "bbb", "bbb", "bbb", "bbb", "ccc");
//按出现次数分组
var sorted = names.stream()
				.collect(Collectors.groupingBy(p -> p, Collectors.counting())).entrySet();

如果我们需要对结果按次数排序,可以如下操作:

var sortedAndGrouping = names.stream().collect(Collectors.groupingBy(p -> p, Collectors.counting())).entrySet().stream()
                .sorted((value1, value2) -> value2.getValue().compareTo(value1.getValue())).map(Map.Entry::getKey).collect(Collectors.toList());

这里实现了分组与排序,并且把list中出现次数最高的放在也第一个元素。

10.List按长度排序

resList.stream().sorted(Comparator.comparingInt(String::length))
                .collect(Collectors.toList());

结语

在实际的开发中,能应用的场景还有很多,我上面列举的一些可能用得会相对多一些,也有很多应用场景我没有提到,java8函数式编程的也许远远不止这些,以后遇到好的场景我再补充,如果大家有好的应用,欢迎留言讨论。

C#实战:5分钟搞定西门子S7-1200 PLC数据读写(S7netplus保姆级教程) 本文详细介绍了如何使用C#和S7netplus库快速实现与西门子S7-1200 PLC的数据读写。从环境准备、连接管理到数据读写高级技巧,提供了保姆级教程和实战方案,帮助开发者绕过常见陷阱,提升工业自动化项目的开发效率。 阅读详情

相关推荐

Livox MID-360与FAST-LIO2实战:从驱动部署到参数调优的完整指南

激光雷达惯性里程计(LIO)是机器人定位与建图(SLAM)领域的核心技术,它通过紧耦合融合激光雷达点云与惯性测量单元(IMU)数据,实现高精度、低漂移的位姿估计。其核心原理在于利用IMU的高频数据预测运动,并用激光雷达的精确测距信息进行校正与优化,从而在快速运动或特征缺失场景下保持鲁棒性。这项技术的工程价值在于为自动驾驶、移动机器人及三维重建提供了可靠的前端里程计解决方案。针对Livox MID-360固态雷达与FAST-LIO2这一热门组合,其应用场景广泛覆盖了室内外导航与地图构建。本文聚焦于**驱动部署

weixin_29997523的博客 448

java8 lambda 表达式 常用语法总结

toList  List&lt;T&gt;      把流中所有元素收集到List中 示例:List&lt;Menu&gt; menus=Menu.getMenus.stream().collect(Collectors.toList()) Joining  String      连接流中每个元素的toString方法生成的字符串 示例:String name=Menu.getMenus.s...

LegendaryHe的博客 768

XGBoost实战:从原理到调参,手把手教你提升模型性能(附Python代码)

本文深入解析XGBoost核心原理,并提供一套从数据准备、系统性调参到生产部署的完整实战指南。通过剖析目标函数、正则化项与分裂算法,帮助读者理解参数背后的数学逻辑,并利用交叉验证、早停法及自动化工具(如Optuna)高效提升模型性能。文中附有详尽的Python代码示例,涵盖类别特征处理、缺失值应对、不平衡数据调整及模型可视化等高级技巧。

weixin_29178069的博客 460

【函数式编程实战】(十) 优雅的处理代码中的时间类

本讲讲解Java以前的Date类、Calender类的缺陷,说明为什么要使用新型的时间类(LocalDate、LocalTime、LocalDateTime、Duration、Period、TemporalAdjuster)并进行实战演示

小明的Java问道之路 1095

ArcGIS供地图斑图形及属性入库操作(附练习数据)

已知数据: 供地图斑位置图。 供地图斑表格 成果要求:将供地图斑导入mdb数据库并将供地图斑表格的属性进行挂接。 接下来我们开始操作: 1、 打开arcmap,在目录内连接的文件夹内找到供地图斑位置图。图片 2、 将annotation和polygon添加到arcmap图片 3、 右击文件所在文件夹新建mdb数据库图片 4、 右击数据库新建要素数据集。(要素数据集非常重要,稍后所有操作都在数据集内进行)选择图斑投影方式及代号。图片 5、 右击要素数据集—导入(将图层内的数据导入数据库)图片 6、 数据导入.

qq_43173805的博客 8132

2026年全国青少年信息素养大赛复赛真题(算法应用主题赛C++初中组:带解析)(7月4日试卷一)【文末附答案和解析】

2026年全国青少年信息素养大赛复赛真题(算法应用主题赛C++初中组:带解析)(7月4日试卷一)【文末附答案和解析】

王老师青少年编程 1741

java8函数式编程实战

函数式编程 函数式编程(Functional Programming) OO(object oriented,面向对象)是抽象数据 FP(Functional programming,函数式编程)是抽象行为 约束 函数式编程是安全的,它增加了一些约束,即所有的数据(变量、对象)必须是不可变的,设置一次,永不改变。不修改自身外部的任何东西(函数范围之外的元素) 优点 不可变对象范式解决了并发编程中棘手问题(当程序的某些部分在多处理器同时运行时),意味着不同的处理器可以尝试同时修改同一块内存。 如果函数

AKA石头 954

记录:解决Ubuntu20.04安装ros报错E: Unable to locate package ros-kinetic-desktop-full【亲测有效】

报错:E: Unable to locate package ros-kinetic-desktop-full.尝试好久一直都无法下载,最后得知真相的我眼泪哗哗的直流。

**My Coding Family** 6万+

【Java基础教程】(二十九)Java新特性篇 · 第九讲:函数式接口——概念及优缺点、语法形式及实战技巧、 内置函数式接口与应用场景~

本文深入介绍了Java的函数式接口。函数式接口是一种只定义了一个抽象方法的接口,可以用于Lambda表达式和方法引用,使得Java代码更加简洁、易读和灵活。 首先,文章解释了为什么函数式接口在Java中如此重要。通过函数式接口,我们可以将行为作为参数传递给方法,从而实现更高层次的抽象和重用。这使得编写更具可读性和可维护性的代码成为可能。 然后,文章详细讨论了如何创建和使用函数式接口。我们可以使用@FunctionalInterface注解来标识一个接口是函数式接口,并确保它只有一个抽象方法。此外,文章还

Technology changes the world of life 3391

目标检测: yolo26在RK3588上部署

YOLO26发布:端到端目标检测新突破 摘要:Ultralytics最新发布的YOLO26算法采用原生端到端设计,无需NMS后处理,显著提升推理效率。该模型基于三大核心原则: 简洁性:消除NMS步骤,实现直接预测 部署效率:简化集成流程,降低延迟 训练创新:引入MuSGD混合优化器,加速收敛 部署教程显示,YOLO26可适配RK3588等边缘设备,通过ONNX转换和RKNN工具链实现高效部署。其创新架构特别优化了分割、姿态估计等专业任务,标志着目标检测技术的重要革新。 (字数:149)

qianxun 1455

ximalaya 新xm-sign逆向思路

本文主要介绍目标网站新xm-sign值的逆向思路。仅代表个人理解,如有其他建议可在评论区沟通。声明仅仅记录一下自己的学习方法,不作为其他参考、更不作为商业用途。如有侵犯请联系本人删除。

weixin_66580433的博客 2017

java8 函数式编程 pdf_java8函数式编程 pdf

java8函数式编程 pdf的重要性就不言而喻了吧。对于每一个JAVA开发者,这都是一个必过的坎。虽然现在的主流编程方式还是面向对象式。当然也不能否认这种方式的健壮性,可扩展性。但是随着编程技术的发展。走在时代前列的函数式编程就粉墨登场了。而这本java8函数式编程就全面介绍了函数式编程的精华,对于很多这种全新的编程理念,大家绝对有必要阅读学习一下。对于JAVA的发展道路非常的有帮助。而这本书主要...

weixin_34277895的博客 1079

RepHead一种重参数化检测头用于提升YOLOv8在困难样本上的检测性能

在目标检测任务中,困难样本通常是指那些由于特殊背景、遮挡、低分辨率或极度小物体等因素,导致模型难以识别的样本。这类样本对传统YOLO系列模型的影响较大,常常造成漏检或误检。重参数化(Reparameterization)是一种深度学习中常用的技术,旨在通过对网络参数的变换,使得模型在训练过程中能够更加灵活地适应不同的数据特征。通过对原始网络结构的参数进行重新表达,能够引导模型在训练过程中学习到更加有效的特征。本文详细介绍了YOLOv8的改进——RepHead检测头,并深入分析了它在解决困难样本检测中的应用。

博客 1210

Java8精华-函数式编程(一)

本文说的是函数式编程的基础知识。将从非常基础的内容开始,本系列文章的主要目的是让新手快速上手。但我确信我们还将讨论大多数有经验的 Java 程序员并没有真正意识到的东西。我们还将研究一些很酷的函数式编程方法,以应对使用 Java 集合处理数据时常见的编程挑战。与面向对象编程一样,我们将对象分配给变量,并将它们发送到方法或从方法接收它们,在函数式编程中,我们将函数分配给变量,并将它们作为实参/参数发送到方法或从方法接收它们。这里所说的函数,是指函数表达式。

weixin_49376454的博客 828

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Java8精华-函数式编程(一)读完这篇,你将彻底理解

与面向对象编程一样,我们将对象分配给变量,并将它们发送到方法或从方法接收它们,在函数式编程中,我们将函数分配给变量,并将它们作为实参/参数发送到方法或从方法接收它们。这里所说的函数,是指函数表达式。Lambda 表达式支持 Java 中的函数式编程。函数式接口充当 lambda 表达式的契约。它们指定 lambda 表达式将接受哪些参数以及返回值是什么。通过 lambda 表达式,所有实现 SAM 接口的匿名内部类都可以转换为 lambda 表达式。

qq_40779721的博客 727

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

深入解析JavaStreamAPI掌握现代函数式编程的精华

中间操作(如filter, map, sorted)总是惰性的(lazy),它们返回一个新的Stream,不会立即执行任何实际的数据处理,只是构建一个操作的流水线。终止操作(如forEach, collect, reduce)则是急切的(eager),它会触发整个流水线的实际计算,并产生一个结果或副作用。在处理无限流(如Stream.generate()或Stream.iterate()创建)时,必须使用short-circuiting操作(如limit())来限制大小,否则程序将不会终止。

JackySun_bo的博客 513

【Kotlin函数式编程实战精华】:掌握高效编码的8大核心技巧

掌握Kotlin函数式编程核心技巧,提升代码简洁性与可维护性。通过高阶函数、Lambda表达式等8大方法结合常见业务场景,详解Kotlin函数编程示例,助你实现高效开发。实用技巧值得收藏。

CompiLume的博客 713

编程精华资源大汇总

wangguo 精华频道 → 互联网 编程精华资源大汇总   2014-04-11  编辑 wangguo 评论(41条) 有7819人浏览 ITeye 专栏 技术 声明:ITeye精华文章的版权属于ITeye网站所有,严禁任何网站转载本文,否则必将追究法律责任! > 猎头职位: 北京: ITe

gyq132104的专栏 5184

JAVA 8函数式编程(二):每个函数都是可以传递的对象

在Java 8中,每个函数都是可以传递的对象,包括静态函数、实例函数与构造函数,唯一需要确认的就是,要传递的函数必须与需要的函数签名一致。首先定义函数接口如下:@FunctionalInterface public interface HelloService { void sayHello(String username); }上面的函数接口只需要一个String参数,所以只要满足此要求的函

甘焕的博客 7502

编程精华资源大汇总 (转)

博客是记录学习历程、分享经验的最佳平台,多年以来,各路技术大牛在ITeye网站上产生了大量优质的技术文章,并将系列文章集结成专栏,以便读者能够更便捷、更系统地浏览学习,这些可称之为“编程精华资源”。 为了便于读者更好地查阅,本文将ITeye中的这些精华资源进行了整理分类,你可以通过文中链接跳转到相应的专栏,希望技术大牛们的这些不可多得的经验分享,能够为你的技术学习、开发之路带来一些帮助。 在此...

iteye_10512的博客 592

JAVA 8函数式编程(四):JAVA支持闭包吗?

如果闭包的定义如此简单,请参看百度百科对闭包的定义: 闭包包含自由(未绑定到特定对象)变量;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。 简单来说,就是可以绑定变量作用域,那么很显然,JAVA是完全支持闭包的,如下:static IntFunction<Integer> sumEx(int a) { // 定义局部变量 fin

甘焕的博客 2466

Java 8学习终极指南:《On Java 8》中文版配套视频讲师答疑精华汇总

《On Java 8》中文版是Java学习者的必备资源,它不仅全面覆盖了Java 8的核心知识点,还与时俱进地增补了Java 11、Java 17的相关内容,贴合实际开发场景,知识点细致,能覆盖市面其他Java书90%的内容。 ## 为什么选择《On Java 8》中文版? 《On Java 8》中文版之所以成为Java学习的热门选择,原因众多。其内容丰富且细致,对于Java 8及后续版本的知

gitblog_01184的博客 411

Java核心技术解析从面向对象到函数式编程的深度探索

记录类(Record)和密封类(Sealed Class)的引入也简化了不可变数据的定义,增强了模式匹配的潜力,为函数式风格提供更多语言层面的支持。然而,在处理集合操作和并发编程时,OOP模式往往需要编写大量样板代码,且容易产生可变状态带来的副作用,增加代码的复杂性和维护成本。它通过吸收函数式思想的精华,提升了语言的表现力和稳健性,同时保持了向后兼容和企业级应用的可靠性。此外,Optional类的引入强制处理空值,避免了NullPointerException,体现了函数式编程的安全性原则。

macjay226的博客 439

Java8【有与无】【精华篇】实用通识

序:本篇内容较多,排版有些乱,希望大家理解 目录 关键词 行为参数化 方法引用 流Stream/parallelStream【构建器模式】 分支步骤 默认方法 (结构)模式匹配【不完全支持】 行为参数化【工厂模式】 Lambda表达式 收集器【静态工厂Collectors】【工厂方法】 并行处理 分支/合并框架 重构、测试和调试 默认方法 Optiona...

琴韵悠悠 1447

精华Java问题总结

当时在网上汇总了不知多少面试和基础题,弄了个精华总结。 1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。 2、short s1= 1; s1= s1+1;有没有错? s1+1运算时会自动提升类型,结果是int,赋值给s1时,将报告需要强转类型的错误。 3、short s1= 1; s1 += 1;有没有错? +=是java规定的运算符,编译器会对它进行特殊处理,因此可以正确编..

少说,多做。 1万+
上一篇: Spring5.0.X源码阅读环境搭建Eclipse4.6.3(neon)
下一篇: Shiro整合SSO单点登录系统
MrCao杰罗尔德
博客等级 码龄10年 117粉丝 23原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值