Java 8新特性之Lambda与函数式编程 下载本文

内容发布更新时间 : 2024/6/11 7:28:17星期一 下面是文章的全部内容请认真阅读。

龙源期刊网 http://www.qikan.com.cn

Java 8新特性之Lambda与函数式编程

作者:杨俊刚 王永和 崔涛 来源:《科学与信息化》2017年第01期

摘 要 Java 8通过添加众多诸如函数式接口、Lambda表达式、类型推断、方法引用、接口默认方法以及增强的Functional类库等新特性,实现了原有语言体系与函数式编程思想的友好共存。

关键词 函数式编程;Lambda表达式;类型推断;回调 前言

Java8问世已将近三年,毫无疑问,Java 8发行版是自Java 5(发行于2004)以来最具革命性的版本。Java 8 为Java语言、编译器、类库、开发工具与JVM(Java虚拟机)带来了大量新特性。在本文中,我们将对Java8中备受瞩目的新特性Lambda展开讨论,分析Lambda是如何在面向对象的语言中融合了函数式编程的特性;Lambda又到底给我们带来了什么便利呢?

1 函数式编程概念简介

在进入正题之前,我们不得不先介绍函数式编程的概念。本节旨在使大家对函数式编程这一编程模式(也可理解为编程思想。当然,我们更容易接触的是面向对象、面向过程的编程思想。我们姑且称之为编程模式吧)有一个初步的了解,本文并不讨论这一种编程模式本身,而是重点讨论在Java8中是如何通过添加大量新特性(甚至不惜修改编译器、修改接口的规范等)来使得Java语言支持函数式编程模式。 1.1 函数式编程的定义

首先请大家看一段摘自维基百科的对函数式编程(Functional Programming)的定义: In computer science, functional programming is a programming paradigm-a style of building the structure and elements of computer programs-that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. (摘自维基百科:https://en.wikipedia.org/wiki/Functional_programming)

简单地翻译一下,也就是说函数式编程是一种编程模型,他将计算机运算看作是数学中函数的计算,并且避免了状态以及变量的概念。 1.2 函数式编程的核心

龙源期刊网 http://www.qikan.com.cn

声明式的代码风格(Declarative Style):这需要提高代码的抽象层次;

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

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

使用高阶函数(High-Order Function):在Java 8以前,重用是建立在对象和类型系统之上。而Java 8中则将重用的概念更进一步,使用函数也能够实现代码的重用。所谓高阶函数,不要被其名字唬住了,实际上很简单: 将函数作为参数传入到另外一个函数中 函数的返回值可以是函数类型 在函数中创建另一个函数 1.3 使用函数式编程的好处

我们先来看一个例子(以下示例并未给出完整的、可运行的所有代码,仅给出了关键部分以供参看)。

假设对于20元以上的商品,进行9折处理,最后得到这些商品的折后价格。 最习惯的实现方式: 例1-1:

BigDecimaltotalOfDiscountedPrices = BigDecimal.ZERO; for(BigDecimalprice : prices) {

if(price.compareTo(BigDecimal.valueOf(20)) > 0){ totalOfDiscountedPrices =

totalOfDiscountedPrices.add(price.multiply(BigDecimal.valueOf(0.9))); }

龙源期刊网 http://www.qikan.com.cn

}

System.out.println(\: \);

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

finalBigDecimaltotalOfDiscountedPrices = 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(\: \);

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

此外,现代的应用程序都会牵涉到多核计算机上的并行运算功能,程序状态就成了一个问题。所有的命令式语言,包括面向对象语言,在涉及多线程时,都会遇到共享对象的状态修改问题。这就是死锁、堆栈跟踪、低级处理器缓存命中率低等问题的根源。如果对象没有状态,这些问题就不存在了(此处不再举例说明)。

总结以上代码示例及事实论述,我们将至少能得到以下三点使用函数式编程的理由: 减少了可变量(Immutable Variable)的声明 代码更加简洁和可读

能够更好地利用并行(Parallelism)

当然,Java 8中对于函数式编程风格的引入,并不是为了要颠覆已经根深蒂固面向对象编程风格。而是让它们和谐共处,取长补短。比如,使用面向对象对实体进行建模,对实体之间