Streams中的断言

ibe*_*beu 3 java assertion java-stream

我知道我可以过滤流只获取那些非空的元素,然后随心所欲地使用它们.像这样的东西:

myList.stream().filter(element -> element != null).doOtherThings...
Run Code Online (Sandbox Code Playgroud)

有没有办法断言元素在流函数中不为空,以便它遍历所有元素,如果它发现一个为null,它会抛出异常?我一直在考虑以下内容:

myList.stream().assert(Objects::nonNull).doOtherThings...
Run Code Online (Sandbox Code Playgroud)

And*_*ner 8

使用类似的东西

.map(Objects::requireNonNull)
Run Code Online (Sandbox Code Playgroud)

你只需要应用一个会引发异常的操作,但是否则会传递参数.

虽然,除非有充分的理由不多次迭代列表,否则将检查和处理分开可能更清楚:

if (myList.stream().anyMatch(Objects::isNull)) {
  throw ...
}
// Do things with list.
Run Code Online (Sandbox Code Playgroud)

  • 但请注意,这里提出的这两种方法并不等效 - 第二种(单独的)检查整个列表中的任何元素是否为空,而第一种(映射步骤)仅检查实际处理的元素,这可能只是一个子集,甚至根本没有,取决于终端操作和管道的其余部分.您需要选择最适合您的用例的内容. (5认同)

Ole*_*.V. 3

已经有一些非常好的建议了。请允许我补充一下。如果您想要的是assert声明中的断言,我想在代码中明确说明这一点,以引导读者了解我的目的。要断言您的原始列表不包含任何nulls:

\n\n
    assert ! myList.contains(null);\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果要在流管道的某个位置检查断言,简单的方法是:

\n\n
    assert myList.stream().map(this::transform).allMatch(Objects::nonNull);\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您不想\xe2\x80\x99 不想为断言创建单独的流,但更喜欢在现有流管道的中间进行断言,请使用例如:

\n\n
        myList.stream()\n                .peek(e -> { assert e != null; })\n                .toArray();\n
Run Code Online (Sandbox Code Playgroud)\n\n

你可能会担心使用起来peek不太好,这也是我最后提到这个选项的原因。peek据记录存在\xe2\x80\x9c主要是为了支持调试\xe2\x80\x9d(断章取义),所以你可能会说它\xe2\x80\x99s与目的相关,assert从而捍卫其使用在这种情况下。

\n