欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 9 Stream API 新增功能

程序员文章站 2022-06-07 10:49:43
...

Java 9 Stream API 新增功能

本文聚焦Java 9 Stream API 新增功能。

1. Stream Takewhile/Dropwhile

假如我们需要生成字符串流,增加一个字符至前一个流的值,直到流当前值的长度小于10.
在java8中如何实现?需要使用短路的中间操作如,limit,allMatch(实际上用于其他目的)。或者基于Spliterator实现自己的takeWhile。总之,把简单问题复杂化。

Java9的实现非常简单:

Stream<String> stream = Stream.iterate("", s -> s + "s")
  .takeWhile(s -> s.length() < 10);

takeWhile操作带一个Predicate参数,其应用于元素决定在所有元素中取最长的前缀(如果流是有序的),或者流所有元素的子集(流是无序的)。

继续学习之前最好理解“最长的前缀”和“流的子集”是什么意思:

  • 最长的前缀:匹配条件的流中连续元素序列. 序列的第一个元素是流的第一个元素, 紧接在序列最后一个元素后面的元素与给定的谓词不匹配。

  • “流的子集:流中匹配条件的部分元素集合。

介绍完这些关键术语后,我们可以较容易地理解另一个新的dropWhile操作。

它恰好是takeWhile的相反操作,如果流是有序的,dropWhile返回的流,是删除了最长前缀后留下元素集合。如果流是无序的,dropWhile返回的流包括删除匹配条件的子集后留下元素的集合。

使用前缀获得流实现丢弃前五个元素:

stream.dropWhile(s -> !s.contains("sssss"));

简言之,dropWhile操作删除对于给定条件返回true的元素,并第一次遇到条件返回false停止删除。

2. Stream Iterate

接着介绍新特性是重载iterate方法实现有限流生成。不要与另一个重载static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)方法混淆,其返回有函数生成的无限顺序序列流。

新的iterate增加了一个predicate决定生成流什么条件必须终止,其使用很方便、简洁:

Stream.iterate(0, i -> i < 10, i -> i + 1)
  .forEach(System.out::println);

其对应的for语句为:

for (int i = 0; i < 10; ++i) {
    System.out.println(i);
}

3. Stream Ofnullable

有时添加至流中的元素可能为null,我们并不希望这样值存在流中。因此需要些if条件语句或三元运算符检查元素是否为null。

假如我们有collection 和 map 变量,内容如下:

List<String> collection = Arrays.asList("A", "B", "C");
Map<String, Integer> map = new HashMap<>() {
    {
        put("A", 10);
        put("C", 30);
    }
};

请看下面示例:

collection.stream()
  .flatMap(s -> {
      Integer temp = map.get(s);
      return temp != null ? Stream.of(temp) : Stream.empty();
    })
  .collect(Collectors.toList());

这里需要判断temp是否为null,导致flatMap方法过于冗长。为了避免使用Stream类的ofNullable方法,相同功能代码非常简洁:

collection.stream()
  .flatMap(s -> Stream.ofNullable(map.get(s)))
  .collect(Collectors.toList());

4. 总结

本文介绍了Java 9 Stream Api中新增的方法,这些增强功能会帮助使用更少的代码实现强大功能。