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内部迭代的好处之一。它还有另一个好处,就是它可以在当数据量比较大的时候,进行并行处理。而不需要我们自己去进行切块,然后再规约了。

posted @ 2021-01-27 23:49  小锅锅要飞  阅读(61)  评论(0)    收藏  举报