流是Java API的新成员,它容许你以声明性方式处理数据集合(经过查询语句来表达,而不是临时编写一个实现)。就如今来讲,你能够把它们当作遍历数据集的高级迭代器。此外,流还能够透明地并行处理。让咱们来看一个实例返回低热量(<400)的菜肴名称:< p=""> java
Java7版本:
List<Dish> lowCaloricDishes = new ArrayList<>();
// 用累加器筛选元素
for(Dish d: menu){
if(d.getCalories() < 400){
lowCaloricDishes.add(d);
}
}
// 用匿名类对菜肴排序
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
public int compare(Dish d1, Dish d2){
return Integer.compare(d1.getCalories(), d2.getCalories());
}
});
// 处理排序后的菜名列表
List<String> lowCaloricDishesName = new ArrayList<>();
for(Dish d: lowCaloricDishes){
lowCaloricDishesName.add(d.getName());
}
Java8版本:
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
List<String> lowCaloricDishesName = menu.stream()
.filter(d -> d.getCalories() < 400) // 选出400卡路里如下的菜肴
.sorted(comparing(Dish::getCalories)) // 按照卡路里排序
.map(Dish::getName) // 提取菜肴名称
.collect(toList()); // 将全部的名称保存在List中
利用多核架构并行执行,只须要把stream()换成parallelStream()复制代码
Java 8中的Stream API特性:数据库
流定义:编程
集合与流之间的差别就在于何时进行计算。集合是一个内存中的数据结构,它包含数据结构中目前全部的值——集合中的每一个元素都得先算出来才能添加到集合中。相比之下,流则是在概念上固定的数据结构(你不能添加或删除元素),其元素则是按需计算的。集合和流的另外一个关键区别在于它们遍历数据的方式。数组
和迭代器相似,流只能遍历一次。遍历完以后,咱们就说这个流已经被消费掉了。如下代码会抛出一个异常,说流已被消费掉了:数据结构
List<String> title = Arrays.asList(“Java8”,”In”, “Action”);
Stream<String> s = title.stream();
s.forEach(System.out::println);
s.forEach(System.out::println);
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at com.lujiahao.learnjava8.chapter4.StreamAndCollection.main(StreamAndCollection.java:16)复制代码
使用Collection接口须要用户去作迭代(好比用for-each),这称为外部迭代。相反,Streams库使用内部迭代架构
集合:用for-each循环外部迭代
List<String> names = new ArrayList<>();
for(Dish d: menu){
names.add(d.getName());
}
集合:用背后的迭代器作外部迭代
List<String> names = new ArrayList<>();
Iterator<String> iterator = menu.iterator();
while(iterator.hasNext()) {
Dish d = iterator.next();
names.add(d.getName());
}
流:内部迭代
List<String> names = menu.stream()
.map(Dish::getName)
.collect(toList());复制代码
java.util.stream.Stream中的Stream接口定义了许多操做。它们能够分为两大类。能够链接起来的流操做称为中间操做,关闭流的操做称为终端操做。中间操做:除非流水线上触发一个终端操做,不然中间操做不会执行任何处理。终端操做:会从流的流水线生成结果。其结果是任何不是流的值。编程语言
流的使用通常包括三件事:函数式编程
流的流水线背后的理念相似于构建器模式。函数
常见流操做:性能
如下是你应从本章中学到的一些关键概念。