集合优化了对象的存储,而流 ( stream ) 与对象的成批处理有关

流是一个与任何特定的存储机制都没有关系的元素序列。事实上,我们说流“没有存储”

不同于在集合中遍历元素,使用流的时候,我们是从一个管道中抽取元素,并对它们进行操作。这些管道通常会被串联到一起,形成这个流上的一个操作管线

流的一个核心优点是,它们能使我们的程序更小,也更好理解。当配合流使用时,lambda 表达式和方法引用就发挥出其威力了。流大大提升了 Java 8 的吸引力

例如,假设我们想按照有序方式显示随机选择的5~20范围内的、不重复的 int 数。因为要对它们进行排序,所以我们可能会把注意力放在选择一个有序的集合上,并基于这样的集合来解决问题。但是借助流,只需要说明想做什么即可:

流可以对有状态的系统进行建模,而不需要赋值或使用可变数据(即声明变量),这一点会非常有用

声明式编程是一种编程风格,我们说明想要完成什么(what),而不是指明怎么做(how),这就是我们在函数式编程中看到的

如果上面的例子使用命令式编程,理解起来要更困难:

像在 ImperativeRandoms 中这样显式地编写迭代机制,称为外部迭代。而在Randoms中,我们看不到任何这样的机制,所以这被称为内部迭代,这是流编程的一个核心特性

内部迭代产生的代码不仅可读性更好,而且更容易利用多处理器:通过放宽对具体迭代方式的控制,我们可以将其交给某种并行化机制

流的另一个重要方面是惰性求值,这意味着它们只在绝对必要时才会被求值

我们可以把流想象成一个“延迟列表”

因为延迟求值,所以流使我们可以表示非常大的(甚至是无限大的)序列,而不用考虑内存问题