Java8集合中的Lambda表达式

标签: Programming Paradigms Java lambda 集合 | 发表时间:2013-10-18 12:52 | 作者:四火
出处:http://www.raychase.net

文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》

Java8集合中的Lambda表达式

本文翻译自《 Java 8 Explained: Applying Lambdas to Java Collections》。

Lambdas表达式是Java 8的主题,在Java平台上我们期待了很久。但是,如果如果我们不在集合中使用它的话,就损失了很大价值。把现有接口迁移成为lambda风格接口的问题已经通过 default methods,也就是defender methods解决了。在这篇文章里面我们来看一看Java集合里面的 批量数据操作(bulk operation)。

批量操作

最初的变更文档已经说了,批量操作是“给Java集合框架添加的用以批量操作数据的功能,而它是基于lambda函数实现的”。引用的话也就是在说,lambda移植到Java 8对我来说的实际目的,就是它提供了一种新的使用集合的方式,这也是最重要的特性,表达式操作符可以并行执行,并且lambda是一个比常规表达式操作符更好的工具。

内部和外部的迭代

历史上,Java集合是不能够表达内部迭代的,而只提供了一种外部迭代的方式,也就是for或者while循环。要描述内部迭代,我们需要用到LambdaJ这样的类库:

 

List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John"));
forEach(persons).setLastName("Doe");

 

从上面的例子可以看出,我们不需要关心last name是怎么被设置到每一个person对象里面去的,也许这样的行为是支持并发执行的。现在我们可以在Java 8中使用类似的表达了:

 

persons.forEach(p -> p.setLastName("Doe"))

 

内部迭代其实和集合的批量操作并没有密切的联系,这只是一个小小的特性,借助它我们感受到语法表达上的变化。真正有意思的和批量操作相关的是新的流(stream)API。

流API

新的 java.util.stream包已经添加进JDK了,现在我们可以借助Java 8执行filter/map/reduce风格的操作了。

流API允许我们声明对数据进行串行或者并行的操作:

 

List persons = …   // sequential version
Stream stream = persons.stream();   //parallel version
Stream parallelStream = persons.parallelStream();

 

java.util.stream.Stream接口提供了批量数据操作的入口,取得了对流实例的引用,我们就可以对集合执行如下有趣的任务了:

Filter

在数据流中实现过滤功能是首先我们可以想到的最自然的操作了。Stream接口暴露了一个filter方法,它可以接受表示操作的 Predicate实现来使用定义了过滤条件的lambda表达式。

 

List persons = …
Stream personsOver18 = persons.stream().filter(p -> p.getAge() > 18);

 

Map

假使我们现在过滤了一些数据,比如转换对象的时候。Map操作允许我们执行一个 Function的实现(Function<T,R>的泛型T,R分别表示执行输入和执行结果),它接受入参并返回。首先,让我们来看看怎样以匿名内部类的方式来描述它:

 

Stream students = persons.stream()
      .filter(p -> p.getAge() > 18)
      .map(new Function() {
                  @Override
                  public Student apply(Person person) {
                     return new Student(person);
                  }
              });

 

现在,把上述例子转换成使用lambda表达式的写法:

 

Stream map = persons.stream()
        .filter(p -> p.getAge() > 18)
        .map(person -> new Student(person));

 

Lambda在把参数传给map方法的时候,实际却并没有使用这个参数,那么我们就可以写成这样:

 

Stream map = persons.stream()
        .filter(p -> p.getAge() > 18)
        .map(Student::new);

 

Collect

“流”抽象天生就该是持续的,我们使用流来描述操作,但是如果我们要获取最终结果的话,必须收集流产生的最终结果。Stream API提供了一系列“最终”的方法, collect()方法就是其中的一个,我们借此可以收集操作的最终结果:

 

List students = persons.stream()
        .filter(p -> p.getAge() > 18)
        .map(Student::new)
        .collect(new Collector>() { … });

 

幸运的是,大多数情况下你不需要自己实现 Collector接口,而是利用 Collectors工具类:

 

List students = persons.stream()
        .filter(p -> p.getAge() > 18)
        .map(Student::new)
        .collect(Collectors.toList());

 

或者,如果我们想使用特定的实现类来收集结果:

 

List students = persons.stream()
        .filter(p -> p.getAge() > 18)
        .map(Student::new)
        .collect(Collectors.toCollection(ArrayList::new));

 

并行和串行

一个使用新的Stream API有趣的特性是它从来都不需要所谓串行或者并行的方法,可以从一开始就并行地消费数据,或者在处理流中的任意时刻转为串行的。

List students = persons.stream()
        .parallel()
        .filter(p -> p.getAge() > 18)  // filtering will be performed concurrently
        .sequential()
        .map(Student::new)
        .collect(Collectors.toCollection(ArrayList::new));

这里有隐藏的一点是,数据处理的并行部分会自动地自我管理,不需要我们自己来处理并发的问题。

总结

好了,要结束了。新的Stream API和lambda表达式给Java 8带来了很多新的特性。当然,在这篇文章以外还有很多没有谈及到,但愿很快我可以给你带给你更多有趣的特性。

文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》

分享到:
你可能也喜欢:

相关 [java8 集合 lambda] 推荐:

Java8集合中的Lambda表达式

- - 四火的唠叨
文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》. 本文翻译自《 Java 8 Explained: Applying Lambdas to Java Collections》. Lambdas表达式是Java 8的主题,在Java平台上我们期待了很久. 但是,如果如果我们不在集合中使用它的话,就损失了很大价值.

Java8之使用新JS解释器Nashorn编译Lambda表达式

- - 并发编程网 - ifeve.com
原文链接  作者: Tal Weiss  CEO of  Takipi   译者:踏雁寻花,xbkaishui  校对:方腾飞. 在最近的一篇 文章中,我了解了一下Java8和Scala是如何实现 Lambda 表达式的. 正如我们所知道的,Java8不仅对javac编辑器做了很大改进,它还加入了一个全新的项目—Nashorn.

大数据Lambda架构

- - CSDN博客云计算推荐文章
1 Lambda架构介绍.          Lambda架构划分为三层,分别是批处理层,服务层,和加速层. 最终实现的效果,可以使用下面的表达式来说明. 1.1 批处理层(Batch Layer, Apache Hadoop).          批处理层主用由Hadoop来实现,负责数据的存储和产生任意的视图数据.

Lambda表达式现状分析

- - InfoQ cn
距明年Java 8发布还有不到一年时间,Brian Goetz发布了最新的 Lambda表达式现状分析,涵盖了Java集合API的改进. Java 8最受期待的特性之一是引入了 Lambda表达式,Java集合API对它的重点支持是确保该类库被广泛使用的关键所在. 如果你不熟悉Lambda表达式的语法,请查看先前的一篇文章 Lambda表达式现状分析以及之前InfoQ的相关报道,以便了解该语法的详细内容.

[Java 8] Lambda 表达式实例

- - Java - 编程语言 - ITeye博客
Java 8 中的 Lambda 表达式,允许将函数作为形参传递给另外的函数. 为了更好地理解,我们用实例的方式来演示如何使用 Lambda 表达式. 1、Lambda 表达式 Hello World. 这是一个最简单的 Lambda 表达式的例子. 首先在 main 方法的上面声明了一个接口 HelloWorld,在 main 方法中实现了这个接口,随后调用了接口的唯一方法.

屌丝就爱尝鲜头——java8初体验 - laozhu1124

- - 博客园_首页
  Java8已经推出,让我们看看他的魅力.   Java8是由Oracle(甲骨文)公司与2014年3月27日正式推出的. Java8同时推出有3套语言系统,分别是Java SE8、Java SE Emebbled 8、Java ME8.   Java SE8较以往的系统增强的功能有:.   ①增强了对集合式操作语言——lambda表达式的支持,“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数.

基于C++ Lambda表达式的程序优化

- sunnyboy.xue - 搜索研发部官方博客
这是一个关于C\C++程序员的一个小故事,关于C++11——刚刚通过的新标准的一个小故事…. 请不要误会,题目中所提及的“优化”并不是提升程序的性能——Lambda表达式干不了这个. 从本质上来说,它只是一种“语法糖”而已. 不使用这种表达式,我们照样可以写出满足需求的程序. 正如放弃C而使用汇编,或者放弃汇编而使用机器语言一样,你能控制的范围就在那里,不增不减.

探索Java语言与JVM中的Lambda表达式(译)

- - BlogJava_首页
探索Java语言与JVM中的Lambda表达式.     Lambda表达式是自Java SE 5引入泛型以来最重大的Java语言新特性,本文是2012年度最后一期 Java Magazine中的 一篇文章,它介绍了Lamdba的设计初衷,应用场景与基本语法. (2013.01.02最后更新).

【译】为什么要在Java中加入Lambda表达式

- - Java - 编程语言 - ITeye博客
原文:http://www.lambdafaq.org/why-are-lambda-expressions-being-added-to-java/. 作者:Maurice Naftalin. Lambda表达式(以及闭包)在许多现代编程语言中都很普及. 在为什么要在 Java 平台加入 Lambda 表达式呢.

基于Lambda架构的股票市场事件处理引擎实践

- - 运维派
CEP(Complex Event Processing)是证券行业很多业务应用的重要支撑技术. 广发证券的IT研发团队,一直关注Storm、Spark、Flink等流式计算的开源技术,也经历了传统Lambda架构的技术演进,在Kappa架构的技术尚未成熟之际,团队针对证券行业的技术现状与特点,采用改良的Lambda架构实现了一个CEP引擎,本文介绍了此引擎的架构并分享了一些股票业务较为有趣的应用场景,以飨同好.