Java 9 Stream API 新增功能

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中新增的方法,这些增强功能会帮助使用更少的代码实现强大功能。

发布了395 篇原创文章 · 获赞 761 · 访问量 143万+

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/103650977