[Java 8] (1) 函数式编程简介

java BigDecimal 类型求和: reduce(BigDecimal.ZERO, BigDecimal::add) reduce(BigDecimal.ZERO, BigDecimal::add); 阅读详情

思维方式的转变

以从一个城市集合中寻找是否存在Chicago为例:
习惯的方式

boolean found = false ;
for ( String city : cities ) {
    if ( city . equals ( "Chicago" )) {
        found = true ;
        break ;
    }
}
System . out . println ( "Found chicago?:" + found );

以上代码就是绝大多数开发人员在面对这个问题时的第一反应。它通过命令式风格(Imperative Style)的代码来完成需要的逻辑,但是看起来会比较复杂,因为代码量较多。

稍有经验的开发人员则会利用现有的API来实现,使代码更简洁同时也更具有可读性,因为它将代码风格由命令式转变为声明式(Declarative Style)。

System . out . println ( "Found chicago?:" + cities . contains ( "Chicago" ));

简单的一行代码,就能够将程序的意图显示出来。
另一个例子
假设对于20元以上的商品,进行9折处理,最后得到这些商品的折后价格。如下解决方案立即会映入脑海:

final List < BigDecimal > prices = Arrays . asList (
    new BigDecimal ( "10" ), new BigDecimal ( "30" ), new BigDecimal ( "17" ),
    new BigDecimal ( "20" ), new BigDecimal ( "15" ), new BigDecimal ( "18" ),
    new BigDecimal ( "45" ), new BigDecimal ( "12" ));

BigDecimal totalOfDiscountedPrices = BigDecimal . ZERO ;
for ( BigDecimal price : prices ) {
    if ( price . compareTo ( BigDecimal . valueOf ( 20 )) > 0 )
        totalOfDiscountedPrices = totalOfDiscountedPrices . add ( price . multiply ( BigDecimal . valueOf ( 0.9 )));
}
System . out . println ( "Total of discounted prices: " + totalOfDiscountedPrices ); 

当你经常性的写这种类型的代码时,不知道是否会产生一种无聊或者不安的情绪。因为这段代码已经普通到有点乏味了,虽然它能够正常工作,但是总会感觉到它并不是那么优雅。
更优雅的方式,是使用声明式的代码:

final BigDecimal totalOfDiscountedPrices = prices . stream ()
    . filter ( price -> price . compareTo ( BigDecimal . valueOf ( 20 )) > 0 )
    . map ( price -> price . multiply ( BigDecimal . valueOf ( 0.9 )))
    . reduce ( BigDecimal . ZERO , BigDecimal: : add );

System . out . println ( "Total of discounted prices: " + totalOfDiscountedPrices );

没有声明任何的临时变量,没有各种if判断,逻辑一气呵成。同时也更具有可读性: 首先将价格集合根据条件进行过滤(filter),然后对过滤后的集合进行折扣处理(map),最后将折扣后的价格进行相加(reduce)。
它利用了Java 8的新特性,Lambda表达式以及相关的方法如stream(),reduce()等将代码转变成函数式的风格(Functional Style)。Lambda表达式和其相关内容会在后文中进行详细介绍。
使用函数式代码的好处

减少了可变量(Immutable Variable)的声明
能够更好的利用并行(Parallelism)
代码更加简洁和可读

当然,Java 8中对于函数式编程风格的引入,并不是为了要颠覆已经根深蒂固面向对象编程风格。而是让它们和谐共处,取长补短。比如,使用面向对象对实体进行建模,对实体之间的关系进行表述;而使用函数式编码来实现实体中的各种状态改变,业务流程以及数据处理。
函数式编程的核心

声明式的代码风格(Declarative Style) : 这需要提高代码的抽象层次,比如在前面的例子中,将从集合中搜索一个元素的操作封装到contains方法中。

更多的不变性(Promote Immutability) : 能不声明变量就不要声明,需要变量时尽量使用final来修饰。因为变量越多,就意味着程序越难以并行。实现了不变性的方法意味着它不再有副作用,不会因为调用而改变程序的状态。

使用表达式来代替语句(Prefer Expression to Statement) : 使用语句也就意味着不变性的破坏和程序状态的改变,比如赋值语句的使用。

使用高阶函数(High-Order Function) : 在Java 8以前,重用是建立在对象和类型系统之上。而Java 8中则将重用的概念更进一步,使用函数也能够实现代码的重用。所谓高阶函数,不要被其名字唬住了,实际上很简单:

将函数作为参数传入到另外一个函数中
函数的返回值可以是函数类型
在函数中创建另一个函数

在前文中,已经见过函数作为参数传入到另一个函数的例子了:

prices . stream ()
    . filter ( price -> price . compareTo ( BigDecimal . valueOf ( 20 )) > 0 )
    . map ( price -> price . multiply ( BigDecimal . valueOf ( 0.9 )))
    . reduce ( BigDecimal . ZERO , BigDecimal: : add );

price -> price.multiply(BigDecimal.valueOf(0.9))实际上就是一个函数。只不过它的写法使用了Lambda表达式,当代码被执行时,该表达式会被转换为一个函数。
函数式接口(Functional Interface)
为了在Java中引入函数式编程,Java 8中引入了函数式接口这一概念。
函数式接口就是仅声明了一个方法的接口,比如我们熟悉的Runnable,Callable,Comparable等都可以作为函数式接口。当然,在Java 8中,新添加了一类函数式接口,如Function,Predicate,Consumer,Supplier等。
在函数式接口中,可以声明0个或者多个default方法,这些方法在接口内就已经被实现了。因此,接口的default方法也是Java 8中引入的一个新概念。
函数式接口使用@FunctionalInterface注解进行标注。虽然这个注解的使用不是强制性的,但是使用它的好处是让此接口的目的更加明确,同时编译器也会对代码进行检查,来确保被该注解标注的接口的使用没有语法错误。
如果一个方法接受一个函数式接口作为参数,那么我们可以传入以下类型作为参数:

匿名内部类(Anonymous Inner Class)
Lambda表达式
方法或者构造器的引用(Method or Constructor Reference)

第一种方式是Java的以前版本中经常使用的方式,在Java 8中不再被推荐。 第二种方式中,Lambda表达式会被编译器转换成相应函数式接口的一个实例。

Java8 函数式编程 Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来对 Java 集合运算和表达的高阶抽象。Stream API 可以极大提高 Java 程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 变换,聚合等。 阅读详情

相关推荐

BigDecimal

【代码】BigDecimal。

MyFreeIT 252

java 8 lamdba 表达式list集合的BigDecimal求和操作

//BigDecimal求和 BigDecimal totalGrade1 = userList.stream().map(Student::getGrade).reduce(BigDecimal.ZERO, BigDecimal::add);//上面的求和不能过滤bigDecimal对象为null的情况,可能会报空指针,这种情况,我们可以用filter方法过滤,或者重写求和方法 //重写求和方法 package com.hanhoo.common.util; import java.math.BigDe

u010741112的博客 8130

江科大笔记—OLED调试工具

OLED介绍及调试工具

m0_62005595的博客 658

Java 8 Stream.reduce() 使用示例

原文地址:https://mkyong.com/java8/java-8-stream-reduce-examples/ 作者:mkyong 翻译:高行行 在 Java 8 中,Stream.reduce()合并流的元素并产生单个值。 使用 for 循环的简单求和运算。 int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int sum...

高行行 1855

TS808效果器制作教程

TS808效果器制作教程 可以在立创商城购买到大部分的电阻电容和IC,音频接口,踩钉,电位器和电源接口可以去某宝看看都买得到的。链接https//pan.baidu.com/s/1QId1eIE3fJ2u5NLBSISvGA。安装过程过于繁琐,把所有元器件按照图纸焊接完成就可以调试了,祝你们成功!这是TS808经典效果器制作过程的记录。IC是JRC4558。...

qq_18948149的博客 3427

HFSS仿真的后处理结果,如何根据天线表面的电流密度分布对天线进行优化?

在HFSS仿真中,天线表面的Jsurf​是最直观、最有价值的诊断工具之一。它不仅告诉你天线“能不能工作”,还能告诉你“为什么工作”以及“哪里出了问题”。

degogmy的博客 1158

Java8

Java8 stream 实现 List 中某个元素加法 BigDecimal repAmount = classAList.stream() .map(ClassA::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); 把classAList中每个元素Cl...

weixin_42987583的博客 1198

content-pipeline:一条可落地的内容生产流水线

content-pipeline 是一种将内容创作工程化的系统性方法,其核心在于用确定性流程替代碎片化人工操作。它基于结构化提示(prompt)、预置叙事框架与品牌参数固化三大原理,实现从素材输入到多平台发布的端到端自动化。技术价值体现在显著降低认知负荷、保障输出一致性、支持本地化资源绑定与闭环反馈校验。典型应用场景包括技术教程批量生成、跨平台(公众号/小红书/即刻)内容适配、AI写作质量可控迭代等。本文深入解析其作为‘内容制造业’基础设施的底层设计逻辑与实操路径,尤其聚焦Claude Code环境下的真实

weixin_31199559的博客 269

Java8函数式编程1-简介和流

编程函数式编程的核心是:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值。 为支持函数式编程,Java8 引入了Lambda表达式。我对Java8中的Lambda表达式的理解是,使用匿名函数替换J

cuiods的博客 1530

InSAR图像配准:从像素级到亚像素级的精度提升策略

本文深入探讨了InSAR图像配准技术,从像素级到亚像素级的精度提升策略。通过分析最大频谱法和相干系数法的适用场景,结合频域补零插值和四叉树分块等高级技术,实现1/8像素级的高精度配准。文章还提供了实用的精度验证方法和常见问题排查指南,为InSAR数据处理提供全面解决方案。

nginx7reverse的博客 836

从零开始:手把手教你设计DP接口电路(含原理图实战)

本文是一份详尽的DisplayPort接口电路设计实战指南。文章从DP接口的核心架构与HDMI的差异讲起,手把手解析了高速差分对、AUX辅助通道、热插拔检测等关键模块的原理图设计要点,并提供了一个完整的DP Source端原理图实例,最后总结了PCB布局与信号完整性的核心考量,旨在帮助硬件工程师高效、稳定地完成DP接口电路设计。

transformer2023的博客 735

Java8函数式编程_1--简介

第1章 简介 主要内容如下: 1.1 为什么需要再次修改Java 1.2 什么是函数式编程 1.3 示例 1.1 为什么需要再次修改Java 1996年1月,Java1.0发布,此后计算机编程领域发生了翻天覆地的变化。商业发展需要更复杂的应用,大多数程序都跑在功能强大的多核CPU机器上。 多核CPU的兴起成为了不容回避的事实。涉及锁的编程算法不但容易出...

Logan的专栏 353

STK相关总结

STK简介 一.SIM卡应用工具包(SIM Application Toolkit),又名CAT/USAT,它包含一系列终端与SIM卡的交互指令,SIM卡可以应用卡内的小应用程序和终端交互,从而实现增值服务的目的,STK包括三种类,STK-imsi切换,STK –OTA,STK-BIP 功能: (1) Profile download:配置下载,开机初始化SIM卡过程中,终端告诉SIM卡终端支持哪些功能,STK中download指终端将数据发送给SIM卡 (2) Proactive command: 主动式

jingjing_2的博客 3356

《Java高并发程序设计》学习 --6.1 Java8的函数式编程简介

1)函数作为一等公民 将函数作为参数传递给另外一个函数,这是函数式编程的特性之一。 函数可以作为另外一个函数的返回值,也是函数式编程的重要特点。 2)无副作用 函数的副作用指的是函数在调用过程中,除了给出了返回值外,还修改了函数外部的状态。比如,函数在调用过程中,修改了一个全局状态。函数式编程认为,函数的副作用应该尽量避免。如果函数都是显式函数,那么函数的执行显然不会受到外部或者全局信息的

sunhaoning的专栏 480

C和C++Everything教程的简介

C和C++Everything教程的简介 C和C++Everything教程,该专栏目前已有8000博文,订阅该专栏相当于同时订阅以下所有收费专栏

希望我的博客,能帮上你解决学习中工作中所遇到的问题 4392

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

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

Java8函数式编程

最近使用lambda表达式,感觉使用起来非常舒服,箭头函数极大增强了代码的表达能力。于是决心花点时间深入地去研究一下java8的函数式。 (想自学习编程的小伙伴请搜索圈T社区,更多行业相关资讯更有行业相关免费视频教程。完全免费哦!) 一、lambda表达式 先po一个最经典的例子——线程 public static void main(String[] args) { // Java7 n...

wanghao112956的博客 2万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java函数式编程详解

Java从1.8以后引入了函数式编程,这是很大的一个改进。函数式编程的优点在提高编码的效率,增强代码的可读性。本文历时两个多月一点点写出来,即作为心得,亦作为交流。 1.Java函数式编程的语法: 使用Consumer作为示例,它是一个函数式接口,包含一个抽象方法accept,这个方法只有输入而无输出也就是说这个方法无返回值。 现在我们要定义一个Consumer接口的实例化对象,传统的方式是...

陈大伟的博客 3万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Java 1.8 函数式编程详解

Java 1.8 函数式编程详解 文章目录Java 1.8 函数式编程详解一. 概述1.1 java 8 新特性:二. 函数式接口2.1 函数式接口概述2.2 Lambda表达式概述2.3 java.util.function介绍 一. 概述 1.1 java 8 新特性: 概述: Java 8 正式版是一个有重大改变的版本,该版本对 Java 做了重大改进。本文章主要讲述java 1.8 函...

暗余的博客 2870

Java函数式编程入门

函数式编程在Java中不仅能提高代码的简洁性和可读性,还能在处理数据流、并行计算等场景中发挥重要作用。通过掌握Lambda表达式、Stream API、Optional以及其他相关技术,并结合实际业务场景的应用,你将能够更高效地开发出安全、稳定和可维护的系统。建议在日常项目中逐步引入函数式编程思想,从简单的集合操作开始,逐步探索更多高级特性,并结合代码评审和测试不断完善实践经验。/*** 函数式编程*//*** Function<T, R>:接受T类型的参数,返回R类型的结果。

zjh285077371的专栏 1779

java8 函数式编程

1.函数式编程思想 a>概念 主要关注对数据进行什么操作, 特点:允许把函数本身作为参数传入另一个函数,还允许返回一个函数! 易于并发编程 2.lambda表达式 a>概念 jdk1.8推出的,对某些匿名内部类写法进行简化, 他是函数编程思想的一个重要体现,不在关注是什么对象,更关注对数据进行什么操作。 b>语法格式 (参数列表)->{代码} ............

我想静静 2450

Java 8 函数式编程详解:从思想到实战

函数式接口是 Java 8 函数式编程的 “桥梁”—— 它是有且仅有一个抽象方法的接口(可包含默认方法、静态方法,Java 8 接口增强特性),用于定义 “函数的形状”(输入参数类型、返回值类型)。若内置接口无法满足需求,可自定义函数式接口(需遵循 SAM 规则):java运行// 自定义:接收两个Integer,返回String的函数式接口// 使用:通过Lambda表达式实现接口TwoIntToString sumToString = (a, b) -> "总和:" + (a + b);

2501_94265850的博客 1245

Java函数式编程

简介 什么是函数式编程 函数式编程是一种编程范式,即一切都是数学函数。在Java面向对象编程中,程序是一系列相互作用(方法)的对象,而在函数式编程中,程序会是一个无状态的函数组合序列。 函数是“第一等公民” “第一等公民”指的是函数和其他数据类型一样,处于平等的地位。可以赋值给变量、可以作为另一个函数的参数或者作为一个函数的返回值。比如 // 将两数相加的逻辑赋值给变量sum var sum = (a,b)->a+b; // 将函数作为另一个函数的参数 operation(sum) Java函数试

Mr_Yao 4096
上一篇: 史上最全Redis面试题,让面试官问无可问(附答案)
下一篇: 分布式链路追踪-skywalking入门体验
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值