Java 8学习笔记之Stream初探
在 Java 8中,流式处理占了非常重要的位置。甚至可以说,Java 8中的函数式处理思想,就是基于Stream实现的。现在,我们可以对Stream有一个认识。
什么是流呢?通俗的说,流就是从支持流式处理操作的数据源生成的元素集合。例如List,Set、数组以及文件等等。我们可以从三个方面,来解读Java 8中的Stream API,第一个是流的常规操作处理;第二个就是对流的结果的处理;第三个就是流的并行化处理。
流的常规操作处理
流的本质就是,它允许以声明性的方式处理数据。此外,他还有两个重要的特点,就是流水线和内部迭代。流水线即是,很多的操作都会返回一个流,我们可以基于这个流再赋予其他的操作,这些操作组合起来就是一个流水线了。内部迭代即对元素的处理是在内部进行的,无需程序员手动处理,这个内部迭代的定义是和Collection接口中的迭代对应的。内部迭代有一个好处就是可以把一些优化放在程序内部,例如流的并行化等等。
好了,说了一大堆,让我们看看Stream的定义吧!
public interface Stream<T> extends BaseStream<T, Stream<T>> {
Stream<T> filter(Predicate<? super T> predicate);
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
Stream<T> distinct();
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
Stream<T> peek(Consumer<? super T> action);
Stream<T> limit(long maxSize);
Stream<T> skip(long n);
void forEach(Consumer<? super T> action);
T reduce(T identity, BinaryOperator<T> accumulator);
...
}
这里,选取了Stream接口的部分抽象方法,我们可以对处理操作选择合适的流水线,例如 filter -> distinct -> limit,然后就可以调用相应的收集方法把最终结果收集起来。
流式处理中的map-reduce
map-reduce架构,是函数式编程中的经典大量数据处理的编程模型。由于Java 8中引入了函数式编程的思想,因此,在Stream中的API中,我们也可以看到它集成了map和reduce方法。
我们知道,map操作是对数据集中的每个数据元素进行处理,然后在reduce中,把所有块中的数据归约起来。
我们可以用班级信息来考虑,例如班级的属性有人数和所在年级。
/**
* @Author: huangpf
* @Des: 班级属性
*/
public class MyClass {
private int count;
private int grade;
...
}
首先我们想要知道这个学校一共有多少人:
public static void mapReduceClasses(List<MyClass> classes) {
Integer count = classes.stream()
.map(MyClass::getCount)
.reduce(0, Integer::sum);
System.out.println("该学校一共有" + count + "人");
}
然后,我们想知道该学校一年级一共有多少人:
public static void mapReduceClasses(List<MyClass> classes) {
Integer count = classes.stream()
.filter(myClass -> myClass.getGrade() == 1)
.map(MyClass::getCount)
.reduce(0, Integer::sum);
System.out.println("该学校一年级有" + count + "人");
}
用map-reduce架构看起来是不是非常直观,而并不需要像之前一样,需要自己显示的编写遍历整个列表,然后根据相应的条件来过滤,再进行求和了,这就是Java 8内部迭代的好处之一。它还有另一个好处,就是它可以在当数据量比较大的时候,进行并行处理。而不需要我们自己去进行切块,然后再规约了。

浙公网安备 33010602011771号