集合类的批处理:
Java8除了Lambda表达式外还提供了另一个重要的特性,即集合的批处理操作,集合类的批处理操作API的目的是实现集合类的“内部迭代”,并期望充分利用现代多核CPU进行并行计算。Java8之前集合类的迭代(Iteration)都是外部的,即客户代码。而内部迭代意味着改由Java类库来进行迭代,而不是客户代码。
例如Java8以前版本要遍历一个集合通常是:
for(Object o: list) { System.out.println(o); }
而在Java8中可以配合Lambda表达式:
list.forEach(o -> System.out.println(o));
集合类中都有forEach方法,方法的参数是一个函数接口Consumer,这个函数式接口有一个accept()方法用来接受单个参数,在forEach方法实现中,accept()接受的参数即为每次遍历集合得到的元素。forEach方法相对于以前的for循环来说也只是用了Lambda使代码更简洁了,但他却是也是串行的操作每个元素,相对于for循环性能上并没有提升,而之前所说的并行执行是由于集合中引入的Stream。
在Java的文档中给出的Stream定义是:
A sequence of elements supporting sequential and parallel aggregate operations.
意思是Stream是一个支持顺序以及并发的集合处理操作的元素序列
Stream接口在java.util.stream包下,主要的实现有IntStream、LongStream、DoubleStream等,Stream对象的创建主要有两种方式:
- 通过Collection接口的默认方法stream()创建
- 通过Stream接口的静态工厂方法of()创建
而Stream接口提供的方法也大致分为了两类:
- 一类对原Stream元素进行筛选、变换、做处理等操作,最终返回一个处理后的新的Stream对象,可以链式调用用多个方法共同处理
- 一类是在得到处理后的新Stream后,用来获取想要的非Stream类型结果,如集合、Stream元素中的最大值、过滤后剩余的元素个数等
Stream部分我发现一个写的很详细的博客,想要深入学习可以参考 http://ifeve.com/stream/
双冒号的使用:
Java8中新加了 ::这种操作符,用来传递方法或者构造方法的引用,这个特性主要是用来简化Lambda表达式,如上面forEach方法的例子,可以简化为:
list.forEach(System.out::println)
要使用这种方法简化Lambda也是有一些限制的,首先Lambda表达式代码块中的代码必须是直接调用了另外的一个方法,并且方法的参数个数、顺序以及类型都必须和对应接口中的抽象方法一致。同样需要得到构造方法的引用,只需要String::new这样,在类后面::new即可