Java 9 Stream API Improvements – Java 9流API的改进

最后修改: 2016年 11月 10日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick write-up, we are going to focus on the new interesting Stream API improvements coming in Java 9.

在这篇快速的文章中,我们将重点介绍Java 9中新的有趣的Stream API改进。

2. Stream Takewhile/Dropwhile

2.流向Takewhile/Dropwhile

Discussions about these methods have appeared repeatedly on StackOverflow (the most popular is this one).

关于这些方法的讨论已经反复出现在StackOverflow上(最受欢迎的是这个)。

Imagine that we want to generate a Stream of Strings by adding one character to the previous Stream‘s value until the length of the current value in this Stream is lower than 10.

想象一下,我们想生成一个StreamStrings,在前一个Stream的值上增加一个字符,直到这个Stream中的当前值的长度小于10

How would we solve it in Java 8? We could use one of the short-circuiting intermediate operations like limit, allMatch that actually serve for other purposes or write our own takeWhile implementation based on a Spliterator that, in turn, complicates such a simple issue.

在Java 8中我们如何解决这个问题呢?我们可以使用其中一个短路的中间操作,如limitallMatch,这些中间操作实际上是为其他目的服务的。Predicate)”>allMatch,它们实际上是为其他目的服务的,或者在takeWhile的基础上编写我们自己的Spliterator,而这又会使这样一个简单的问题复杂化。

With Java 9, the solution is easy:

有了Java 9,解决这个问题就很容易了。

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

The takeWhile operation takes a Predicate which is applied to elements to determine the longest prefix of these elements (if a stream is ordered) or a subset of the stream’s elements (when a stream is unordered).

takeWhile操作需要一个Predicate,它被应用于元素以确定这些元素的最长前缀(如果流是有序的)或流的元素的子集(当流是无序的)。

To move forward, we had better understand what terms “the longest prefix” and “a Stream’s subset” mean:

为了向前推进,我们必须更好地理解 “最长的前缀 “和 “一个Stream的子集 “等术语的含义。

  • the longest prefix is a contiguous sequence of elements of the stream that match the given predicate. The first element of the sequence is the first element of this stream, and the element immediately following the last element of the sequence does not match the given predicate
  • a Stream’s subset is a set of some (but not all) elements of the Stream match the given predicate.

After introducing these key terms, we can easily comprehend another new dropWhile operation.

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

It does exactly the opposite of takeWhile. If a stream is ordered, the dropWile returns a stream consisting of the remaining elements of this Stream after dropping the longest prefix of elements that match the given predicate.

它的作用与takeWhile正好相反。如果一个流是有序的,dropWile返回一个由这个Stream的剩余元素组成的流,在去掉符合给定谓词的最长前缀的元素之后。

Otherwise, if a Stream is unordered, the dropWile returns a stream consisting of the remaining elements of this Stream after dropping a subset of elements that match the given predicate.

否则,如果一个Stream是无序的,dropWile返回一个由这个Stream的剩余元素组成的流,在丢弃一个符合给定谓词的元素子集后。

Let’s throw away the first five elements by using the preceding obtained Stream:

让我们通过使用前面获得的Stream来抛开前五个元素。

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

Simply put, the dropWhile operation will remove elements while the given predicate for an element returns true and stops removing on the first predicate’s false.

简单地说,dropWhile操作将在某个元素的给定谓词返回true时删除元素,并在第一个谓词的false时停止删除。

3. Stream Iterate

3.流迭代

The next new feature is the overloaded iterate method for finite Streams generation. Not to be confused with the finite variant which returns an infinite sequential ordered Stream produced by some function.

下一个新特性是重载的iterate方法,用于有限Streams生成。不要与finite变体混淆,后者返回由某些函数产生的无限连续的有序Stream

A new iterate slightly modifies this method by adding a predicate which applies to elements to determine when the Stream must terminate. Its usage is very convenient and concise:

一个新的iterate稍稍修改了这个方法,增加了一个适用于元素的谓词,以确定流必须终止的时间。它的用法是非常方便和简洁的。

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

It can be associated with the corresponding for statement:

它可以与相应的for语句关联。

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

4. Stream Ofnullable

4.Stream Ofnullable

There are some situations when we need to put an element into a Stream. Sometimes, this element may be a null, but we don’t want that our Stream contains such values. It causes of writing either an if statement or a ternary operator which checks whether an element is a null.

有些情况下,我们需要将一个元素放入Stream中。有时,这个元素可能是一个null,但我们不希望我们的Stream包含这样的值。这就需要写一个if语句或一个三元操作符来检查一个元素是否为null.

Assuming that collection and map variables, have been created and filled successfully, have a look at the following example:

假设collectionmap变量,已经被成功创建和填充,请看下面的例子。

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

To avoid such boilerplate code, the ofNullable method has been added to the Stream class. With this method the preceding sample can be simply transformed into:

为了避免这种模板代码,ofNullable方法已经被添加到Stream类中。有了这个方法,前面的例子可以简单地转化为。

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

5. Conclusion

5.结论

We considered major changes of Stream API in Java 9 and how these improvements will help us to write more emphatic programs with fewer efforts.

我们考虑了Java 9中Stream API的主要变化,以及这些改进将如何帮助我们以更少的努力编写更强调的程序。

As always, the code snippets can be found over on Github.

一如既往,代码片段可以在Github上找到over