Java 新增的Stream方法

Java 新增的Stream方法,用户希望使用 Java 9 为 Stream 接口添加的新特性,使用 Stream 接口新增的 ofNullableiteratetakeWhile 以及 dropWhile 方法。Java 9 为 Stream 接口引入了 ofNullableiteratetakeWhiledropWhile 等新方法,本范例将讨论它们的用法。

Java 新增的Stream方法 问题描述

用户希望使用 Java 9 为 Stream 接口添加的新特性。

Java 新增的Stream方法 解决方案

使用 Stream 接口新增的 ofNullableiteratetakeWhile 以及 dropWhile 方法。

Java 新增的Stream方法 具体实例

Java 9 为 Stream 接口引入了 ofNullableiteratetakeWhiledropWhile 等新方法,本范例将讨论它们的用法。
1.ofNullable方法
在 Java 8 中,of 方法包括两种形式,一种传入单个值,另一种传入可变参数列表。无论哪种形式,参数都不能为空。
而在 Java 9 中,新的 ofNullable 方法可以在参数不为空时返回一个包装值的单元素流,为空时返回一个空流。例 10-16 的用例显示了该方法的应用。

例 10-16 ofNullable 方法的应用

@Test
public void ofNullable() throws Exception {
    Stream<String> stream = Stream.ofNullable("abc");  ➊
    assertEquals(1, stream.count());
 
    stream = Stream.ofNullable(null);                  ➋
    assertEquals(0, stream.count());
}

❶ 单元素流
❷ 返回 Stream.empty()
在本例中,count 方法返回流中非空元素的数量,我们可以借此在任何参数上使用 ofNullable 方法,而无须首先检查参数是否为空。

2.传入Predicateiterate方法
另一种有趣的方法是 iterate。在 Java 8 中,iterate 方法的签名如下:

static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

创建流时,从初始元素种子开始,对种子依次应用一元运算符以产生后续元素。由于生成的流是一个无限流,通常需要采用 limit 或其他短路操作(short-circuiting operation,如 findFirstfindAny)来控制返回流的大小。
在 Java 9 中,iterate 方法新增了一种重载形式,它传入 Predicate 作为第二个参数:

static<T> Stream<T> iterate(T seed, Predicate<? super T> hasNext,
    UnaryOperator<T> next)

创建流时,从初始元素种子开始,对种子应用一元运算符,直至值不再满足谓词 hasNext
相关应用如例 10-17 所示。

例 10-17 传入 Predicateiterate 方法

@Test
public void iterate() throws Exception {
    List<BigDecimal> bigDecimals =                ➊
            Stream.iterate(BigDecimal.ZERO, bd -> bd.add(BigDecimal.ONE))
            .limit(10)
            .collect(Collectors.toList());
 
    assertEquals(10, bigDecimals.size());
 
    bigDecimals = Stream.iterate(BigDecimal.ZERO, ➋
            bd -> bd.longValue() < 10L,
            bd -> bd.add(BigDecimal.ONE))
            .collect(Collectors.toList());
 
    assertEquals(10, bigDecimals.size());
}

❶ 创建 BigDecimal 流(Java 8 实现)
❷ 创建 BigDecimal 流(Java 9 实现)
第一个流使用 iterate 方法,并通过 limit 方法控制大小,这是 Java 8 的实现方式;第二个流传入 Predicate 作为第二个参数,看起来更像是传统的 for 循环。

3.takeWhiledropWhile方法
Java 9 新增了 takeWhiledropWhile 方法,二者基于谓词获取流的某一部分。根据 Javadoc 的描述,对于有序流,takeWhile 方法从流的起始位置开始,返回“匹配给定谓词的元素的最长前缀”。
dropWhile 方法的作用正好相反,在丢弃匹配给定谓词的元素的最长前缀后,该方法将返回流的其余元素。
两种方法在有序流上的应用如例 10-18 所示。

例 10-18 获取与丢弃流中的元素

@Test
public void takeWhile() throws Exception {
    List<String> strings = Stream.of("this is a list of strings".split(" "))
            .takeWhile(s -> !s.equals("of"))  ➊
            .collect(Collectors.toList());
    List<String> correct = Arrays.asList("this", "is", "a", "list");
    assertEquals(correct, strings);
}
 
@Test
public void dropWhile() throws Exception {
    List<String> strings = Stream.of("this is a list of strings".split(" "))
            .dropWhile(s -> !s.equals("of"))  ➋
            .collect(Collectors.toList());
    List<String> correct = Arrays.asList("of", "strings");
    assertEquals(correct, strings);
}

❶ 当不再满足谓词时,返回谓词之前的元素
❷ 当不再满足谓词时,返回谓词之后的元素
可以看到,两种方法在同一个位置将流拆分,不过 takeWhile 返回拆分位置之前的元素,而 dropWhile 返回拆分位置之后的元素。
takeWhile 方法的最大优点在于它是一种短路操作:对于一个包含大量排序元素的集合,只要达到所设定的条件,就可以停止求值。
例如,假设存在一个由客户订单构成的集合,集合中的元素以降序方式排序。借由 takeWhile 方法,我们可以只获取高于某个阈值的订单,而不必筛选每个元素。
例 10-19 模拟了这种情况。程序生成 50 个 0 到 100 之间的随机整数,对它们做降序排序,然后仅返回大于 90 的整数。

例 10-19 对整数流应用 takeWhile 方法

Random random = new Random();
List<Integer> nums = random.ints(50, 0, 100) ➊
        .boxed()                             ➋
        .sorted(Comparator.reverseOrder())
        .takeWhile(n -> n > 70)              ➌
        .collect(Collectors.toList());

❶ 生成 50 个 0 到 100 之间的随机整数
❷ 将这些整数装箱,以便采用 Comparator 排序并收集
❸ 将流拆分并返回大于 90 的整数
改用 dropWhile 方法或许能让本例看起来更为直观(尽管效率未必会提高),如例 10-20 所示。

例 10-20 对整数流应用 dropWhile 方法

Random random = new Random();
List<Integer> nums = random.ints(50, 0, 100)
        .sorted()                ➊
        .dropWhile(n -> n < 90)  ➋
        .boxed()
        .collect(Collectors.toList());

❶ 升序排序
❷ 将流拆分并返回大于 90 的整数
类似 takeWhiledropWhile 这样的方法在其他语言中已存在多年,Java 9 将二者正式引入 Java。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程