Java Null-Safe Streams from Collections – 从集合中获得的Java空值安全流

最后修改: 2018年 8月 6日

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

1. Overview

1.概述

In this tutorial, we’ll learn how to create null-safe streams from Java collections.

在本教程中,我们将学习如何从Java集合中创建空安全的流。

To fully understand this material, some familiarity with Java 8’s Method References, Lambda Expressions, Optional and Stream API is required.

为了充分理解本材料,需要对Java 8的方法引用、Lambda表达式、Optional和Stream API有一定的熟悉程度。

If you’re unfamiliar with any of these topics, you can take a look at these previous articles first: New Features in Java 8, Guide To Java 8 Optional and Introduction to Java 8 Streams.

如果您对这些主题不熟悉,可以先看一下以前的这些文章。Java 8 的新功能Guide To Java 8 OptionalIntroduction to Java 8 Streams

2. Maven Dependency

2.Maven的依赖性

Before we begin, there’s one Maven dependency that we’ll need for certain scenarios:

在我们开始之前,有一个Maven依赖,我们在某些情况下会需要它。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.2</version>
</dependency>

The commons-collections4 library can be downloaded from Maven Central.

commons-collections4库可以从Maven中心下载。

3. Creating Streams From Collections

3.从集合中创建流

The basic approach for creating a Stream from any type of Collection is to call the stream() or parallelStream() methods on the collection, depending on the type of stream that’s required:

从任何类型的集合中创建Stream的基本方法是在集合上调用stream()parallelStream()方法,这取决于需要的流的类型。

Collection<String> collection = Arrays.asList("a", "b", "c");
Stream<String> streamOfCollection = collection.stream();

Our collection will most likely have an external source at some point. We’ll probably end up with a method similar to the one below when creating streams from collections:

我们的集合很可能在某个时候有一个外部源。当从集合中创建流时,我们可能最终会采用类似于下面的方法。

public Stream<String> collectionAsStream(Collection<String> collection) {
    return collection.stream();
}

This can cause some problems. When the provided collection points to a null reference, the code will throw a NullPointerException at runtime.

这可能会导致一些问题。当提供的集合指向一个null引用时,代码将在运行时抛出一个NullPointerException

The following section addresses how we can protect against this.

下一节将讨论我们如何防止这种情况的发生。

4. Making Created Collection Streams Null-Safe

4.使创建的集合流成为空值安全的

4.1. Add Checks to Prevent Null Dereferences

4.1.添加检查以防止Null Dereferences

To prevent unintended null pointer exceptions, we can opt to add checks to prevent null references when creating streams from collections:

为了防止意外的null指针异常,我们可以选择在从集合中创建流时添加检查以防止null引用

Stream<String> collectionAsStream(Collection<String> collection) {
    return collection == null 
      ? Stream.empty() 
      : collection.stream();
}

This method, however, has a couple of issues.

然而,这种方法有几个问题。

First, the null check gets in the way of the business logic decreasing the overall readability of the program.

首先,null检查妨碍了业务逻辑,降低了程序的整体可读性。

Second, the use of null to represent the absence of a value is considered the wrong approach post-Java SE 8; there’s a better way to model the absence and presence of a value.

其次,使用null来表示一个值的缺失被认为是Java SE 8之后的错误做法;有一个更好的方法来模拟一个值的缺失和存在。

It’s important to keep in mind that an empty Collection isn’t the same as a null Collection. While the first one indicates that our query doesn’t have results or elements to show, the second one suggests that a kind of error just happened during the process.

重要的是要记住,一个空的Collection和一个null Collection是不一样的。前者表明我们的查询没有结果或元素可以显示,而后者则表明在这个过程中发生了某种错误。

4.2. Use emptyIfNull Method From CollectionUtils Library

4.2.使用CollectionUtils库中的emptyIfNull方法

We can opt to use the Apache Commons’ CollectionUtils library to make sure our stream is null safe. This library provides an emptyIfNull method, which returns an immutable empty collection given a null collection as an argument, or the collection itself otherwise:

我们可以选择使用Apache Commons的CollectionUtils库来确保我们的流是null安全的。这个库提供了一个emptyIfNull方法,该方法在给定一个null集合作为参数的情况下,返回一个不可变的空集合,否则就是集合本身。

public Stream<String> collectionAsStream(Collection<String> collection) {
    return emptyIfNull(collection).stream();
}

This is a very simple strategy to adopt; however, it depends on an external library. If a software development policy restricts the use of such a library, then this solution is rendered null and void.

这是一个非常简单的策略,但是,它依赖于一个外部库。如果软件开发政策限制使用这样的库,那么这个解决方案就会变得无效和失效。

4.3. Use Java 8’s Optional

4.3.使用Java 8的Optional

Java SE 8’s Optional is a single-value container that either contains a value or doesn’t. Where a value is missing, the Optional container is said to be empty.

Java SE 8的Optional是一个单值容器,要么包含一个值,要么不包含。当缺少一个值时,Optional容器被认为是空的。

Using Optional can arguably be considered the best overall strategy to create a null-safe collection from a stream.

使用Optional可以说是从流中创建一个空安全集合的最佳整体策略。

Let’s see how we can use it, followed by a quick discussion below:

让我们看看如何使用它,然后在下面进行快速讨论。

public Stream<String> collectionToStream(Collection<String> collection) {
    return Optional.ofNullable(collection)
      .map(Collection::stream)
      .orElseGet(Stream::empty);
}
  • Optional.ofNullable(collection) creates an Optional object from the passed-in collection. An empty Optional object is created if the collection is null.
  • map(Collection::stream) extracts the value contained in the Optional object as an argument to the map method (Collection.stream()).
  • orElseGet(Stream::empty) returns the fallback value in the event that the Optional object is empty, i.e the passed-in collection is null.

As a result, we proactively protect our code against unintended null pointer exceptions.

因此,我们主动保护我们的代码不受意外的null指针异常的影响。

4.4. Use Java 9’s Stream OfNullable

4.4.使用Java 9的Stream OfNullable

Examining our previous ternary example in section 4.1., and considering the possibility that some elements could be null instead of the Collection, we have at our disposal the ofNullable method in the Stream class.

检查我们之前在第4.1节中的三元组例子,并考虑到一些元素可能是null而不是Collection,我们在Stream类中有ofNullable方法可以使用。

We can transform the above example to:

我们可以将上述例子转化为。

Stream<String> collectionAsStream(Collection<String> collection) {  
  return collection.stream().flatMap(s -> Stream.ofNullable(s));
}

5. Conclusion

5.结论

In this article, we briefly discussed how to create a stream from a given collection. We then proceeded to explore the three key strategies for making sure the created stream is null-safe when created from a collection.

在这篇文章中,我们简要地讨论了如何从一个给定的集合中创建一个流。然后,我们继续探讨了三个关键策略,以确保从集合中创建的流是安全的。

Finally, we pointed out the disadvantages of using each strategy where relevant.

最后,我们在相关地方指出了使用每种策略的缺点。

As usual, the full source code that accompanies the article is available over on GitHub.

像往常一样,伴随着这篇文章的完整源代码可以在GitHub上获得