一、方法分类

Stream提供了大量的方法进行聚集操作,这些方法既可以是“中间的”,也可以是“末端的”。

  • 中间方法:中间操作允许流保持打开状态,并允许直接调用后续方法。上面程序中的map()方法就是中间方法。中间方法的返回值是另外一个流。
  • 末端方法:末端方法是对流的最终操作。当对某个Stream执行末端方法后,该流将会被“消耗”且不再可用。上面程序中的sum()、count()、average()等方法都是末端方法。

除此之外,关于流的方法还有如下两个特征:

  • 有状态的方法:这种方***给流增加一些新的属性,比如元素的唯一性、元素的最大数量、保证元素以排序的方式被处理等。有状态的方法往往需要更大的性能开销。
  • 短路方法:短路方法可以尽早结束对流的操作,不必检查所有的元素。

下面简单介绍一下Stream常用的中间方法:

  • filter(Predicate predicate):过滤Stream中所有不符合predicate的元素。
  • mapToXxx(ToXxxFunction mapper):使用ToXxxFunction对流中的元素执行一对一的转换,该方法返回的新流中包含了ToXxxFunction转换生成的所有元素。
  • peek(Consumer action):依次对每个元素执行一些操作,该方法返回的流与原有流包含相同的元素。该方法主要用于调试。
  • distinct():该方法用于排序流中所有重复的元素(判断元素重复的标准是使用equals()比较返回true)。这是一个有状态的方法。
  • sorted():该方法用于保证流中的元素在后续的访问中处于有序状态。这是一个有状态的方法。
  • limit(long maxSize):该方法用于保证对该流的后续访问中最大允许访问的元素个数。这是一个有状态的、短路方法。

下面简单介绍一下Stream常用的末端方法:

  • forEach(Consumer action):遍历流中所有元素,对每个元素执行action。
  • toArray():将流中所有元素转换为一个数组。
  • reduce():该方法有三个重载的版本,都用于通过某种操作来合并流中的元素。
  • min():返回流中所有元素的最小值。
  • max():返回流中所有元素的最大值。
  • count():返回流中所有元素的数量。
  • anyMatch(Predicate predicate):判断流中是否至少包含一个元素符合Predicate条件。
  • noneMatch(Predicate predicate):判断流中是否所有元素都不符合Predicate条件。
  • findFirst():返回流中的第一个元素。
  • findAny():返回流中的任意一个元素。

除此之外,Java 8允许使用流式API来操作集合,Collection接口提供了一个stream()默认方法,该方法可返回该集合对应的流,接下来即可通过流式API来操作集合元素。由于Stream可以对集合元素进行整体的聚集操作,因此Stream极大地丰富了集合的功能。

Java 8新增了Stream、IntStream、LongStream、DoubleStream等流式API,这些API代表多个支持串行和并行聚集操作的元素。上面4个接口中,Stream是一个通用的流接口,而IntStream、LongStream、DoubleStream则代表元素类型为int、long、double的流。

Java 8还为上面每个流式API提供了对应的Builder,例如Stream.Builder、IntStream.Builder、LongStream.Builder、DoubleStream.Builder,开发者可以通过这些Builder来创建对应的流。

独立使用Stream的步骤如下:

  1. 使用Stream或XxxStream的builder()类方法创建该Stream对应的Builder。
  2. 重复调用Builder的add()方法向该流中添加多个元素。
  3. 调用Builder的build()方法获取对应的Stream。
  4. 调用Stream的聚集方法。

在上面4个步骤中,第4步可以根据具体需求来调用不同的方法,Stream提供了大量的聚集方法供用户调用,具体可参考Stream或XxxStream的API文档。对于大部分聚集方法而言,每个Stream只能执行一次。