简体   繁体   中英

Assertions in Streams

I know I can filter a stream to get only those elements that are not null, and then do with them whatever I need. Something like this:

myList.stream().filter(element -> element != null).doOtherThings...

Is there a way to assert that the elements are not null in a stream function, so that it goes through all elements and if it finds one being null, it throws an exception? I've been thinking of something like the following:

myList.stream().assert(Objects::nonNull).doOtherThings...

Use something like

.map(Objects::requireNonNull)

You just need to apply an operation which will throw an exception, but otherwise passes the argument through.

Although, unless there is a good reason not to iterate the list multiple times, it might be clearer to separate the checking and the processing:

if (myList.stream().anyMatch(Objects::isNull)) {
  throw ...
}
// Do things with list.

To the map method I prefer to use peek method. I think it is more expressive then uing map method that has to return some value.

    list.stream()
            .peek(Objects::requireNonNull)

However what i think is hard to understand is that stream is not executed until the collect() is called. That is why doing this kind of conditional logic is hard using streams. To be honest if you want to achieve the desired effect you have to do something like this.

list.stream()
            .peek(Objects::requireNonNull)
            .collect(Collectors.toList())
            .stream()
            .map(t -> do whatever ... )

There are some very good suggestions already. Allow me to supplement. If what you are after is an assertion as in an assert statement, I would like to make this explicit in the code in order to guide the reader about my purpose. To assert that your original list doesn't contain any null s:

    assert ! myList.contains(null);

If the assertion is to be checked somewhere down the stream pipeline, the simple way is:

    assert myList.stream().map(this::transform).allMatch(Objects::nonNull);

If you don't want to create a separate stream for the assertion but prefer to assert in the middle of your existing stream pipeline, use for example:

        myList.stream()
                .peek(e -> { assert e != null; })
                .toArray();

You may worry that the use of peek is not so nice, which is also why I mention this option last. peek is documented to exist “mainly to support debugging” (quote taken out of its context), so you may say that it's related to the purpose of assert and thus defend its use in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM