简洁Java之道
作者:网络转载 发布时间:[ 2015/7/22 11:14:30 ] 推荐标签:测试开发技术
函数式编程
函数式编程将函数作为程序开发人员的核心结构。开发人员可以以一种非常灵活的方式使用函数,例如将其作为参数传递。利用Lambda表达式的这种能力,Java可以将函数作为方法的参数,或者将代码作为数据。Lambda表达式可以看作是一个与任何特定的类都无关的匿名方法。这些理念有着非常丰富多彩并且引人入胜的数学基础。
函数式编程和Lambda表达式仍然是比较抽象、深奥的概念。对于开发人员来说,主要关注如何解决实际生产中的任务,对于跟踪新的计算趋势可能并不感兴趣。随着Lambda表达式在Java中的引入,对于开发人员来说对这些新特性的了解至少需要能够达到可以读懂其他开发人员所编写代码的程度。这些新特性还能带来实际的好处——可以影响并发系统的设计,使其拥有更优的性能。而本文所关心的是如何利用这些机制编写简洁而又清晰的代码。
之所以能够用Lambda表达式生成简洁的代码,有如下几个原因。局部变量的使用量减少,因此声明和赋值的代码也随之减少。循环被方法调用所替代,从而将三行以上的代码缩减为一行。本来在嵌套循环和条件语句中的代码现在可以放置于一个单独的方法中。实现连贯接口,可以将方法以类似于Unix管道的方式链接在一起。以函数式的风格编写代码的净效应并不只限于可读性。此类代码可以避免状态维护并且不会产生副作用。这种代码还能够产生易于并行化,提高处理效率的额外收益。
Lambda表达式
与Lambda表达式相关的语法比较简单直白,不过又有别于Java之前版本的习语。一个Lambda表达式由三部分组成,参数列表、箭头和主体。参数列表可以包含也可以不包含括号。此外还新增了由双冒号组成的相关操作符,可以进一步缩减某些特定的Lambda表达式所需的代码量。这又称为方法引用。
线程创建
在这个示例中,将会创建并运行一个线程。Lambda表达式出现在赋值操作符的右侧,指定了一个空的参数列表,以及当线程运行时写到标准输出的简单的消息输出。
Runnable r1 = () -> System.out.print("Hi!");
r1.run()

处理集合
Lambda表达式的出现会被开发人员注意到的首要位置之一是与集合API相关。假设我们需要将一个字符串列表根据长度排序。
java.util.List<String> l;
l= java.util.Arrays.asList(new String[]{"aaa", "b", "cccc", "DD"});
可以创建一个Lambda表达式实现此功能。
java.util.Collections.sort(l, (s1, s2) ->
new Integer(s1.length()).
compareTo(s2.length())
这个示例中包含两个传递给Lambda表达式体的参数,以比较这两个参数的长度。

除此之外还有许多替代方案,在无需使用标准的“for”或“while”循环的前提下,可以操作列表中的各个元素。通过向集合的“forEach”方法传入Lambda表达式也可以完成用于比较的语义。这种情况下,只有一个参数传入,也无需使用括号。
l.forEach(e -> System.out.println(e));

这个特殊的示例还可以通过使用方法引用将包含类和静态方法分开的方式进一步减少代码量。每个元素都会按顺序传入println方法。
l.forEach(System.out::println)
java.util.stream是在Java 8中新引入的包,以函数式程序开发人员所熟悉的语法处理集合。在包的摘要中对包中的内容解释如下:“为流元素的函数式操作提供支持的类,如对集合的map-reduce转换。”
下方的类图提供了对该包的一个概览,着重介绍了接下来的示例中将要用到的功能。包结构中列示了大量的Builder类。这些类与连贯接口一样,可以将方法链接成为管道式的操作集。

字符串解析和集合处理虽然简单,在真实世界中仍有许多实际应用场景。在进行自然语言处理(NLP)时,需要将句子分割为单独的词。生物信息学将DNA和RNA表示为有字母组成的碱基,如C,G,A,T或U。在每个问题领域中,字符串对象会被分解,然后针对其各个组成部分进行操作、过滤、计数以及排序等操作。因此,尽管示例中所包含的用例十分简单,其理念仍适用于各类有实际意义的任务。

sales@spasvo.com