Welcome 微信登录

首页 / 软件开发 / JAVA / 从命令式编程到Fork/Join再到Java 8中的并行Streams

从命令式编程到Fork/Join再到Java 8中的并行Streams2014-08-30 infoq 译:臧秀涛Java 8带来了很多可以使编码更简洁的特性。例如,像下面的代码:

Collections.sort(transactions, new Comparator<Transaction>(){public int compare(Transaction t1, Transaction t2){return t1.getValue().compareTo(t2.getValue());}});
可以用替换为如下更为紧凑的代码,功能相同,但是读上去与问题语句本身更接近了:

transactions.sort(comparing(Transaction::getValue));
Java 8引入的主要特性是Lambda表达式、方法引用和新的Streams API。它被认为是自20年前Java诞生以来语言方面变化最大的版本。要想通过详细且实际的例子来了解如何从这些特性中获益,可以参考本文作者和Alan Mycroft共同编写的《Java 8 in Action: Lambdas, Streams and Functional-style programming》一书。

这些特性支持程序员编写更简洁的代码,还使他们能够受益于多核架构。实际上,编写可以优雅地并行执行的程序还是Java专家们的特权。然而,借助新的Streams API,Java 8改变了这种状况,让每个人都能够更容易地编写利用多核架构的代码。

在这篇文章中,我们将使用以下三种风格,以不同方法计算一个大数据集的方差,并加以对比。

命令式风格

Fork/Join框架

Streams API

方差是统计学中的概念,用于度量一组数的偏离程度。方差可以通过对每个数据与平均值之差的平方和求平均值来计算。例如,给定一组表示人口年龄的数:40、30、50和80,我们可以这样计算方差:

计算平均值:(40 + 30 + 50 + 80) / 4 = 50

计算每个数据与平均值之差的平方和:(40-50)2 + (30-50)2 + (50-50)2 + (80-50)2 = 1400

最后平均:1400/4 = 350

命令式风格

下面是计算方差的一种典型的命令式风格实现:

public static double varianceImperative(double[] population){ double average = 0.0; for(double p: population){average += p; } average /= population.length; double variance = 0.0; for(double p: population){ variance += (p - average) * (p - average); } return variance/population.length;}
为什么说这是命令式的呢?我们的实现用修改状态的语句序列描述了计算过程。这里,我们显式地对人口年龄数组中的每个元素进行迭代,而且每次迭代时更新average和variance这两个局部变量。这种代码很适合只有一个CPU的硬件架构。确实,它可以非常直接地映射到CPU的指令集。