Java8集合中的Lambda表达式_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java8集合中的Lambda表达式

Java8集合中的Lambda表达式

 2013/10/19 0:47:23  RayChase  程序员俱乐部  我要评论(0)
  • 摘要:本文翻译自《Java8Explained:ApplyingLambdastoJavaCollections》。Lambdas表达式是Java8的主题,在Java平台上我们期待了很久。但是,如果如果我们不在集合中使用它的话,就损失了很大价值。把现有接口迁移成为lambda风格接口的问题已经通过defaultmethods,也就是defendermethods解决了。在这篇文章里面我们来看一看Java集合里面的批量数据操作(bulkoperation)。批量操作最初的变更文档已经说了
  • 标签:Lambda表达式 Java 表达式

本文翻译自《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对我来说的实际目的,就是它提供了一种新的使用集合的方式,这也是最重要的特性,表达式caozuofu.html" target="_blank">操作符可以并行执行,并且lambda是一个比常规表达式操作符更好的工具。

内部和外部的迭代

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

?

1 2 class="java plain" style="margin: 0px !important; padding: 0px !important; border: 0px !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; vertical-align: baseline !important; background-image: none !important; overflow: visible !important; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; float: none !important; height: auto !important; line-height: 1.1em !important; width: auto !important; direction: ltr !important; display: inline !important;">List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John")); forEach(persons).setLastName("Doe");

?

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

?

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

?

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

流API

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

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

?

1 2 3 List persons = …?? // sequential version Stream stream = persons.stream();?? //parallel version Stream parallelStream = persons.parallelStream();

?

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

Filter

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

?

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

?

Map

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

?

1 2 3 4 5 6 7 8 Stream students = persons.stream() ??????.filter(p -> p.getAge() > 18) ??????.map(new Function() { ??????????????????@Override ??????????????????public Student apply(Person person) { ?????????????????????return new Student(person); ??????????????????} ??????????????});

?

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

?

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

?

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

?

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

?

Collect

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

?

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

?

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

?

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

?

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

?

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

?

并行和串行

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

1 2 3 4 5 6 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带来了很多新的特性。当然,在这篇文章以外还有很多没有谈及到,但愿很快我可以给你带给你更多有趣的特性。

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

发表评论
用户名: 匿名