Drools_user
Drools_user

Reputation: 231

Checking if a list is empty in java 8

I am new to Java8. I have implemented lists and filters. I have done a null check in my code. I would appreciate some help with how to check if the list is not empty in the same code snippet. If the list is not empty then the code should proceed with the assertion.

    list.stream().filter(listElement -> listElement != null).
    forEach((listElement) -> Assert.assertEquals(
        ValueType.CANDY,
        listElement.getCandyType()));

Upvotes: 21

Views: 143859

Answers (4)

Johnny
Johnny

Reputation: 15413

The chosen answer is great, just a small suggestion to handle null case with Optional.ofNullable of the newly introduced to Java8 Optional class:

  Optional.ofNullable(list)
            .orElseGet(Collections::emptyList)
            .stream().filter(Objects::nonNull)
            .map(listElement -> listElement.getCandyType())
            .forEach(candyType -> Assert.assertEquals(ValueType.CANDY, candyType)););

Upvotes: 28

Holger
Holger

Reputation: 298143

You are asking an obsolete question. Streams process all elements of a source, hence, if there are no elements, no action will be taken. Therefore, you don’t need to check whether the list is empty.

Still, you can simplify your code:

list.stream().filter(Objects::nonNull)
    .map(listElement -> listElement.getCandyType())
    .forEach(candyType -> Assert.assertEquals(ValueType.CANDY, candyType));

or

Assert.assertTrue(list.stream().filter(Objects::nonNull)
                      .map(listElement -> listElement.getCandyType())
                      .allMatch(Predicate.isEqual(ValueType.CANDY));

allMatch follows the rules required for this check. If there are no elements, there is no contradicting element, hence all match. Note that listElement -> listElement.getCandyType() also can be replaced by a method reference of the form ClassName::getCandyType; I didn’t do it here as I don’t know the correct class name.

There is no performance difference between both variants. allMatch will return immediately when encountering the first non-matching element, and assertEquals will throw on the first non matching element. In the second case, the stack trace won’t show artifacts of the stream API implementation.

The second one is preferred when you provide checks for production code rather than unit tests and allow to turn these checks off, as with the Java Language assert feature, e.g.

assert list.stream().filter(Objects::nonNull)
           .map(listElement -> listElement.getCandyType())
           .allMatch(Predicate.isEqual(ValueType.CANDY));

as this form guarantees that there will be no overhead when assertions are turned off, whereas the first variant, having an assert statement with the forEach action may still cause iterating over all elements and performing the intermediate steps of the pipeline.

Upvotes: 32

sisyphus
sisyphus

Reputation: 6392

Asserting that the list is empty is a separate thing from asserting that any particular element of the list has some form (i.e. getCandyType() == ValueType.CANDY). Trying to tie the two ideas together ever is just not the right way to do things.

What you need to do is to add a second assertion, either before or after the forEach, which does

assertThat(list.isEmpty(), not(equalTo(Boolean.FALSE)))

... or anything similar.

One of the major points about empty lists is that they can be processed in the same way as lists containing elements. This is why things like the Optional class and the Null pattern exist. So if you really care that the list is empty you really should make it a separate, distinct assertion.

Upvotes: 0

Buddy
Buddy

Reputation: 11028

Check out the isEmpty method

if (list.isEmpty()) { ... }

Here's the doc: https://docs.oracle.com/javase/7/docs/api/java/util/List.html#isEmpty()

Upvotes: 9

Related Questions