Java 8必将掀起Java函数式编程热潮

  Java 8给Java带来了一场变革。很明显,这个版本是过去十年以来推出的最具份量的Java更新,其中囊括了海量新特性,包括默认方法、方法与构造函数引用以及Lambda函数等等。

  其中最有趣的一项特性当数全新java.util.streamAPI,它作为Javadoc状态存在,能够对元素流进行函数式操作,例如在集合中进行map-reduce变换。

  将这个新API与Lambda表达式相结合,我们就得到了一条简洁但却强大的语法,能够对应用程序中的代码进行大幅简化。

  就以表面上看起来相当简单的集合过滤任务为例。在这一实例中,我们如下所示创建Message Collection type:

  创建一个Messages Collection

List<Message> messages = new ArrayList<>();  messages.add(new Message("aglover", "foo", 56854));  messages.add(new Message("aglover", "foo", 85));  messages.add(new Message("aglover", "bar", 9999));  messages.add(new Message("rsmith", "foo", 4564));

  在这个集合中,我打算将delay(第三个构造函数参数)在3000秒以上作为条件对Message进行全面过滤。在Java 8之前的版本中,大家可以用以下方式表达这类逻辑:

  传统过滤方式

for (Message message : messages)  {            if (message.delay > 3000)        {                    System.out.println(message);          } }

  不过在Java 8中,这项工作将变得更加简单明了。集合如今支持stream方法,它能够将底层数据结构转化为可重复的对象流,从而实现使用Lambda表达式的全新函数式操作。大多数此类操作都可以被串连起来。这些可串连方法被称为intermediate,那些无法被串连的方法则被表示为terminal。

  简要来讲,Lambda表达式与匿名类基本相似,只不过摒弃了大量语法限制。举例来说,如果大家在查看Javadoc以寻找Stream中filter方法的对应参数,各位会发现它拥有一个Predicate type。不过我们不需要像在Java 8之前的版本中那样利用匿名类来实现这一对接。因此,Predicate Lambda表达式能够过滤掉所有数值高于3000的条目,如下所示:

  Lambda表达式

x -> x.delay > 3000

  其中的x正是被传送至集合流内每一个值的参数,而->符号右侧的所有内容都作为表达式估值。将这些结合起来,就成了Java 8中的处理方式:

  Lambda表达式流

messages.stream().filter(m -> m.delay > 3000).forEach(item -> System.out.println(item));

  有趣的是,由于Java 8中的其它一些新特性,我们还可以对forEach的Lambda表达式进行进一步简化:

  Lambda表达式流还能进一步简化

messages.stream().filter(m -> m.delay > 3000).forEach(System.out::println);

  由于forEach Lambda表达式的参数仅仅单纯作用于println,Java 8现在允许我们直接对参数进行整体对接。

  之前我曾经提到过,集合流允许大家将各个Lambda表达式串连起来——在上面的例子中,filter方法属于一项intermediate方法,而forEach则是一项terminal方法。其它能够为函数程序员快速识别出的intermediate方法还包括:map、flatMap以及reduce等,这里就不一一列举了。

  具体来讲,我希望找到Message当中所有延迟周期超过3000秒的条目并计算它们的总计延迟时长。如果没有函数魔法作为辅助,我只能如下进行:

  普通Java写法

long totalWaitTime = 0; for (Message message : messages)  {           if (message.delay > 3000)         {                    totalWaitTime += message.delay;           } }

  然而随着Java 8的面世与大量新函数的出现,大家可以实现更为精致的代码结构,具体如下:

  文艺Java 8写法

long totWaitTime = messages.stream().filter(m -> m.delay > 3000).mapToLong(m -> m.delay).sum();

  请注意我将filter与mapToLong方法进行串连的方式,再加上一条terminal sum。顺便说一句,sum方法需要使用一种特殊的映射方法类型才能产生原始type集合,例如mapToLong以及mapToInt等等。

  函数式编程作为一大核心语言特性,能够为开发者带来令人叹为观止的强大构建能力。虽然大部分此类技术已经能够在各类第三方库(例如Guava)以及JVM语言(例如Scala与Groovy)中找到,但将这些关键特性融入Java仍然能够吸引更为广泛的开发者受众、并给未来的开发前景带来深远影响。

  毫无疑问,Java 8的出现让Java在通往完美的道路上再度迈出一大步。

文章相关课程 Java开发实用工具及组件应用(JFreeChart、PDF组件-iText、jasper report报表、Maven) 基于JavaEE平台实战WebService框架Xfire+Ajax框架DWR(租房网项目实战) 基于ibatis、spring、struts2.0技术实战开发企业级ERP进销存管理项目(权限、Ajax、Jquery)

时间: 2024-11-17 08:07:43

Java 8必将掀起Java函数式编程热潮的相关文章

Java FP: Java中函数式编程的谓词函数(Predicates)第一部分

你一直在听说函数式编程将称霸整个编程届,而自己仍然沉浸在普通的Java里?请不要担心,因为你已经在日常Java代码中加入了函数式编程的特性.此外,函数式编程很有趣,能够帮你节省多行代码并且降低错误率. 什么是谓词函数? 许久之前,那时我还在用Java 1.4进行编码,当我第一次发现Apache Commons Collections,便爱上了谓词函数.Apache Commons Collections里的谓词函数仅仅只是一个只有一个方法的接口: evaluate(Object object):

Java函数式编程(七):MapReduce_java

译注:map(映射)和reduce(归约,化简)是数学上两个很基础的概念,它们很早就出现在各类的函数编程语言里了,直到2003年Google将其发扬光大,运用到分布式系统中进行并行计算后,这个组合的名字才开始在计算机界大放异彩(那些函数式粉可能并不这么认为).本文我们会看到Java 8在摇身一变支持函数式编程后,map和reduce组合的首次亮相(这里只是初步介绍,后续还会有针对它们的专题). 对集合进行归约 现在为止我们已经介绍了几个操作集合的新技巧了:查找匹配元素,查找单个元素,集合转化.这

基于范型的java函数式编程(一)

编程|函数 注:在您阅读本篇的时候,希望你对Java Generic(范型)能够有所了解和明白. 记:周末在给javaparty讲FP中,很多人似乎对fp并不关心,也认为java中fp的作用不大.其实这是个很大的观念错误,范型的发展,对java的函数式编程支持很大,对Functor的影响也非常大.Functor在算法.逻辑.条件计算.规则引擎等等方面,都会有很大的作为,这个影响可就会深远的多了.-- 估且以此篇的开端,唤醒java开发者对FP in Java的重新认识. 周六给javaparty

浅谈Java 8的函数式编程

关于"Java 8为Java带来了函数式编程"已经有了很多讨论,但这句话的真正意义是什么? 本文将讨论函数式,它对一种语言或编程方式意味着什么.在回答"Java 8的函数式编程怎么样"之前,我们先看看Java的演变,特别是它的类型系统,我们将看到Java 8的新特性,特别是Lambda表达式如何改变Java的风景,并提供函数式编程风格的主要优势. 函数式编程语言是什么? 函数式编程语言的核心是它以处理数据的方式处理代码.这意味着函数应该是第一等级(First-cla

Java FP: Java中函数式编程的谓词函数(Predicates)第二部分

在上一篇文章中我们介绍了谓词函数.通过一个简单的只带一个返回值是true或者false的函数的接口,把函数式编程语言的优势带入到了类似Java的面向对象编程语言中.这一小节,我们将会介绍一些高级特性,方便你高效利用谓词函数. 测试 在测试代码中使用谓词的优势尤为明显.当你需要测试一个混合了数据结构与某些条件逻辑的方法时,通过使用谓词,你可以先单独测试数据结构,再测试条件逻辑. 第一步,先利用永真谓词或者永假谓词屏蔽用于判断的逻辑,将注意力集中在测试数据结构上: 1 // check with t

Java函数式编程(一):你好,Lambda表达式_java

第一章 你好,lambda表达式! 第一节 Java的编码风格正面临着翻天覆地的变化. 我们每天的工作将会变成更简单方便,更富表现力.Java这种新的编程方式早在数十年前就已经出现在别的编程语言里面了.这些新特性引入Java后,我们可以写出更简洁,优雅,表达性更强,错误更少的代码.我们可以用更少的代码来实现各种策略和设计模式. 在本书中我们将通过日常编程中的一些例子来探索函数式风格的编程.在使用这种全新的优雅的方式进行设计编码之前,我们先来看下它到底好在哪里. 改变了你的思考方式 命令式风格--

Java函数式编程(三):列表的转化_java

列表的转化 将集合转化成一个新的集合就和遍历它一样简单.假设我们要将列表中的名字转化成全大写的.我们看下都有哪些实现方式. Java中的字符串是不可变的,所以它没法改变.我们可以生成新的字符串,用来替换列表中原有的元素.然而这样做的话,原来列表就没了;还有一个问题,原来的列表可能也是不可变的,比如Arrays.asList()生成的,所以修改原来的列表这招不行.还有一个缺点就是这样做很难并行操作. 生成一个新的全大写的列表是个不错的选择. 乍听起来这个建议弱爆了;性能是我们都很关注的一个问题.令

Java函数式编程(八):字符串及方法引用_java

第三章 字符串,比较器和过滤器 JDK引入的一些方法对写出函数式风格的代码很有帮助.JDK库里的一些的类和接口我们已经用得非常熟悉了,比如说String,为了摆脱以前习惯的那种老的风格,我们得主动寻找机会来使用这些新的方法.同样,当我们需要用到只有一个方法的匿名内部类时,我们现在可以用lambda表达式来替换它了,不用再像原来那样写的那么繁琐了. 本章我们会使用lambda表达式和方法引用来遍历字符串,实现Comparator接口,查看目录中的文件,监视文件及目录的变更.上一章中介绍的一些方法还

Java函数式编程(二):集合的使用_java

第二章:集合的使用 我们经常会用到各种集合,数字的,字符串的还有对象的.它们无处不在,哪怕操作集合的代码要能稍微优化一点,都能让代码清晰很多.在这章中,我们探索下如何使用lambda表达式来操作集合.我们用它来遍历集合,把集合转化成新的集合,从集合中删除元素,把集合进行合并. 遍历列表 遍历列表是最基本的一个集合操作,这么多年来,它的操作也发生了一些变化.我们使用一个遍历名字的小例子,从最古老的版本介绍到现在最优雅的版本. 用下面的代码我们很容易创建一个不可变的名字的列表: 复制代码 代码如下: