Java中λ表达式并行与组合行为

  

  

串行指一个步骤一个步骤地处理,也就是通常情况下,代码一行一行地执行。

  

如果将我们常用的迭代器式的循环展开的话,就是串行执行了循环体内所定义的操作:

        和+=arr.get (0);   和+=arr.get (1);   和+=arr.get (2);//?/pre>      

在书的一开始,就提到Java需要支持集合的并行计算(而λ为这个需求提供了可能)。

  

这些功能将全部被实现于库代码中,对于我们使用者,实现并行的复杂性被大大降低(最低程度上只需要调用相关方法)。

  

另外,关于并发与并行这两个概念,其实是不同的,如果不明白的话请自行了解,在此只引用一句非常流行的话:

  

一个是关于代码结构,一个是关于代码执行。

  

如果我们想将一个计算任务均匀地分配给CPU的四个内核,我们会给每个核分配一个用于计算的线程,每个线程上进行整个任务的子任务。

  

书上有一段非常形象的伪代码:

        如果任务列表包含超过N/4元素{   leftTask=task.getLeftHalf ()   rightTask=task.getRightHalf ()   doInparallel {   leftResult=leftTask.solve ()   rightResult=rightTask.solve ()   }   结果=结合(leftResult rightResult)   其他}{   结果=task.solveSequentially ()   }      

代码中,将每四个任务元素分为一组,用四个内核对其进行并行处理,然后每两组进行一次结果的合并,最终得到整个任务队列的最终结果。

  

从整体处理流程上看,先将任务队列递归地进行分组,并行处理每一组,然后将结果递归地进行合并(合并通过管道终止操作实现)。

  

Java8之前,开发者们使用一种针对集合的fork/join框架来实现该模式。

  

然而现在,想对代码进行性能优化,就是一件非常容易的事了。

  

还记得我们上一节中所得出的最终代码:

        长validContactCounter=contactList.stream ()   . map (s→新联系人().setName (s))   .filter(联系人::调用)    .count ();      

稍加改动:

        长validContactCounter=contactList.parallelStream ()   . map (s→新联系人().setName (s))   .filter(联系人::调用)    .count ();      

  

同时下图将展示如何根据四个核对上述任务进行分解处理,最终合并结果并终止管道。

  

注意递归分解的目的是使子任务们足够小来串行执行。

  

  

Java写手应该知道,Java中并不存在纯粹的“函数”,只存在“方法”。也就是说,Java中的函数必须依赖于某一个类,或者作为类的某种行为存在。

  

而在其他语言中,存在纯函数,以CoffeeScript的语法、声明一个函数:

        吃=(x)→   alert (" # {x} eatten !”)      

这种写法与λ表达式的语法非常相近,也就是说,相比于匿名内部类,λ表达式看上去更像是一种函数表达式。

  

对于函数,一个核心操作便是组合。如果要求一元二次函数的其中一个解sqrt (sqr (b) - 4 * * c),便是对多个子函数进行了组合。

  

对于面向对象,我们通过解耦的方式来分解它,同样,我们也希望以此种方式分解一个函数行为。

  

首先,沿用上两节中使用的例子,对接触类稍作修改,将名字属性分拆为名和姓:

        私人字符串firstName;   私人字符串lastName;      

假设我们现在想要对联系人们进行排序,创建自定义排序的Java标准方式是创建一个比较器:

        公共接口Comparator{   int比较(T o1、o2);//?   }      

我们想通过比较名的首字母来为联系人排序:

        ComparatorbyFirstName=new Comparator () {   @Override   公共int比较(o1,接触o2) {   返回Character.compare (o1.getFirstName () .charAt (0) o2.getFirstName () .charAt (0));   }   };      

λ写法:

        ComparatorbyFirstNameLambdaForm=(o1、o2)→   Character.compare (o1.getFirstName () .charAt (0) o2.getFirstName () .charAt (0));      

写完这段代码后,想法立即提醒我代码可以替换为Comparator.comparingInt(…),不过这是后话,暂且不表。

  

在上面的代码中,我们发现了组合行为,即

Java中λ表达式并行与组合行为