Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

它看起来就像一个工厂的流水线一样,每一步都会对数据进行处理,乍一看好像没区别啊。我们来看看普通的处理和使用Stream处理有什么不一样:

public static void main(String[] args) {
  	//这是普通的处理
    List<String> list = new ArrayList<>();
    list.add("A");
    list.add("B");
    list.add("C");
  
  	//移除为B的元素
  	Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()){
        if(iterator.next().equals("B")) iterator.remove();
    }
  
  	//这是通过Stream的处理
    list = list     //链式调用
            .stream()    //获取流
            .filter(e -> !e.equals("B"))   //只允许所有不是B的元素通过流水线
            .collect(Collectors.toList());   //将流水线中的元素重新收集起来,变回List
    System.out.println(list);
}

传统方式:
同样是一批数据,直接编写操作对数据处理相当于吧这一批数据处理完之后,又开始下一个步骤继续处理这一批数据,每一步需要等到上一步结束之后,拿到上一批数据才能开始下一步,每一个流程依次进行:
stream01
而Stream则是提前编排好流程,每一个元素依次独立走完流水线,无需按批次完成:

(1,2,3) → 1 → 2 → 3 → 合并

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
list.stream()
        .map(x -> {
            System.out.println("我是第一步: " + x);
            return x;
        })  //map可以对实现接受一种类型的数据,转为同类型或另一类型的数据
        .map(x -> {
            System.out.println("我是第二步: " + x);
            return x;
        })
        .forEach(System.out::println);

实际上,在我们调用Stream的各种方法时,并不是像我们之前那样直接对数据进行处理,而是在进行编排,直到我们调用最后一步forEach或是collect这种收尾的方法时,整个流水线才开始运作(不相信可以试试看去掉最后的收尾操作,不会有任何操作执行)这也是Stream的一种惰性的体现。

注意: 后续我们学习多线程之后,Stream甚至还能利用多线程,同时开展N条流水线进行处理,大大提升数据处理效率。