Java Streams:查找stream是否包含null

tka*_*uko 7 java java-8 java-stream

最有可能是重复,但我无法找到任何特定的.

特定

public static void main(String[] args) {
    System.out.println(
            Arrays.asList(null, null, 1)
                    .stream()
                    .filter(obj -> obj == null)
                    .findAny()
                    .isPresent()
    );
}
Run Code Online (Sandbox Code Playgroud)

期望

至少应该工作(即返回false因为findAny返回Optional).

实际

NullPointerException 被扔了

这是一个错误还是一个功能?

感谢您的意见和解释.

小智 10

此行为在Javadoc中突出显示为findAny() https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#findAny--

返回:描述此流的某个元素的Optional,如果流为空,则返回空Optional

抛出:NullPointerException - 如果选择的元素为null

由于您正在过滤以使Stream仅包含空值,因此您将获得预期的NullPointerException.


Fed*_*ner 8

如果您将代码更改为使用anyMatch而不是filter(...).findAny().isPresent(),则按预期工作:

boolean found = Arrays.asList(null, null, 1)
        .stream()
        .anyMatch(Objects::isNull);

System.out.println(found); // true
Run Code Online (Sandbox Code Playgroud)

至于为什么您的版本因NPE而失败,在Stream.findAny文档中说:

抛出:

NullPointerException - if the element selected is null

所以这是预期的行为.


编辑: NPE发生因为Optional.of用于构造返回的值findAny().并且Optional.of根据文档需要非空值:

返回具有指定的当前非null值的Optional.

无论如何,我想你想知道为什么在构建由... 返回的值时Optional.of使用而不是Optional.ofNullablefindAny()

好吧,我只能猜测,但我认为,findAny()findFirst()是为了查找符合某些条件的,即一个值Person,其名称开头A.可能是您想知道null流中是否有元素的情况.但在这种情况下,你并不需要真正找到这样的元素,因为你已经知道,如果你找到它,这将是,嗯...只是null.因此,仅检查您的流是否包含就足够了null,您可以完美地使用它anyMatch()来查找是否属于这种情况.

换句话说,找到一个元素是没有多大用处的null,因为你不能对它做任何事情(除了知道它之外null).


编辑2:正如用户@ holi-java在下面的评论中指出的,如果findAny()返回Optional.ofNullable(null),则无法知道是否null找到了.在这种情况下,结果将是模糊的,因为Optional.ofNullable(null).equals(Optional.empty()) == true,即它会导致混淆,因为Optional.ofNullable(null).isPresent() == false,意味着没有找到匹配的值.

  • @Federico Peralta Schaffner:原则上,搜索条件可以*包括*`null`作为可能的结果,而不是搜索*exact*`null`.但是,这可以被视为罕见的极端情况.我从来没有需要这个.除此之外,如果我想知道列表是否包含`null`,我会使用`list.contains(null)`而不是使用流API ... (3认同)