Java 新增的Stream方法,用户希望使用 Java 9 为 Stream 接口添加的新特性,使用 Stream 接口新增的 ofNullable、iterate、takeWhile 以及 dropWhile 方法。Java 9 为 Stream 接口引入了 ofNullable、iterate、takeWhile、dropWhile 等新方法,本范例将讨论它们的用法。
Java 新增的Stream方法 问题描述
用户希望使用 Java 9 为 Stream 接口添加的新特性。
Java 新增的Stream方法 解决方案
使用 Stream 接口新增的 ofNullable、iterate、takeWhile 以及 dropWhile 方法。
Java 新增的Stream方法 具体实例
Java 9 为 Stream 接口引入了 ofNullable、iterate、takeWhile、dropWhile 等新方法,本范例将讨论它们的用法。
1.ofNullable方法
在 Java 8 中,of 方法包括两种形式,一种传入单个值,另一种传入可变参数列表。无论哪种形式,参数都不能为空。
而在 Java 9 中,新的 ofNullable 方法可以在参数不为空时返回一个包装值的单元素流,为空时返回一个空流。例 10-16 的用例显示了该方法的应用。
例 10-16 ofNullable 方法的应用
❶ 单元素流
❷ 返回 Stream.empty()
在本例中,count 方法返回流中非空元素的数量,我们可以借此在任何参数上使用 ofNullable 方法,而无须首先检查参数是否为空。
2.传入Predicate的iterate方法
另一种有趣的方法是 iterate。在 Java 8 中,iterate 方法的签名如下:
创建流时,从初始元素种子开始,对种子依次应用一元运算符以产生后续元素。由于生成的流是一个无限流,通常需要采用 limit 或其他短路操作(short-circuiting operation,如 findFirst 或 findAny)来控制返回流的大小。
在 Java 9 中,iterate 方法新增了一种重载形式,它传入 Predicate 作为第二个参数:
创建流时,从初始元素种子开始,对种子应用一元运算符,直至值不再满足谓词 hasNext。
相关应用如例 10-17 所示。
例 10-17 传入 Predicate 的 iterate 方法
❶ 创建 BigDecimal 流(Java 8 实现)
❷ 创建 BigDecimal 流(Java 9 实现)
第一个流使用 iterate 方法,并通过 limit 方法控制大小,这是 Java 8 的实现方式;第二个流传入 Predicate 作为第二个参数,看起来更像是传统的 for 循环。
3.takeWhile与dropWhile方法
Java 9 新增了 takeWhile 和 dropWhile 方法,二者基于谓词获取流的某一部分。根据 Javadoc 的描述,对于有序流,takeWhile 方法从流的起始位置开始,返回“匹配给定谓词的元素的最长前缀”。
dropWhile 方法的作用正好相反,在丢弃匹配给定谓词的元素的最长前缀后,该方法将返回流的其余元素。
两种方法在有序流上的应用如例 10-18 所示。
例 10-18 获取与丢弃流中的元素
❶ 当不再满足谓词时,返回谓词之前的元素
❷ 当不再满足谓词时,返回谓词之后的元素
可以看到,两种方法在同一个位置将流拆分,不过 takeWhile 返回拆分位置之前的元素,而 dropWhile 返回拆分位置之后的元素。
takeWhile 方法的最大优点在于它是一种短路操作:对于一个包含大量排序元素的集合,只要达到所设定的条件,就可以停止求值。
例如,假设存在一个由客户订单构成的集合,集合中的元素以降序方式排序。借由 takeWhile 方法,我们可以只获取高于某个阈值的订单,而不必筛选每个元素。
例 10-19 模拟了这种情况。程序生成 50 个 0 到 100 之间的随机整数,对它们做降序排序,然后仅返回大于 90 的整数。
例 10-19 对整数流应用 takeWhile 方法
❶ 生成 50 个 0 到 100 之间的随机整数
❷ 将这些整数装箱,以便采用 Comparator 排序并收集
❸ 将流拆分并返回大于 90 的整数
改用 dropWhile 方法或许能让本例看起来更为直观(尽管效率未必会提高),如例 10-20 所示。
例 10-20 对整数流应用 dropWhile 方法
❶ 升序排序
❷ 将流拆分并返回大于 90 的整数
类似 takeWhile 和 dropWhile 这样的方法在其他语言中已存在多年,Java 9 将二者正式引入 Java。