简体   繁体   中英

Best way to check collections not null & null conditions

we use collections like ArrayList,hashmap & many more.

Number of times we have check condition like whether list is null or not.

We have many ways to chek whether our collection is null or not.

Different ways.

1. if(list==null)
2. if(list.size()==0)
3. if(list.isEmpty())

Also sometimes we also need to check whether list is not null , so we normally check it by these ways

1. if(list!=null)
2. if(list.size()>0)
3. if(!list.isEmpty()) 

Which is best condition or do we need to make some combination of these considering performance of program execution?

Best combination would be

if(list!=null && !list.isEmpty()){

        //Yeah ,do something
}

One for null check, and then any thing there or not check

1. if(list!=null)

You should make sure that is never the case!!

Read Effective Java 2nd Edition by Joshua Bloch
Item 43: Return empty arrays or collections, not nulls

[...] In summary, there is no reason ever to return null from an array- or collection-valued method instead of returning an empty array or collection. The null-return idiom is likely a holdover from the C programming language, in which array lengths are returned separately from actual arrays. In C, there is no advantage to allocating an array if zero is returned as the length.

In short, let your methods return Collections.emptyList() instead of null and you've got one thing less to worry about.

2. if(list.size()>0)
3. if(!list.isEmpty()) 

That depends. For a simple collection such as ArrayList, they are equivalent. But what if your Collection is actually a live view of a Database query? Calling size() might me a very expensive operation, whereas isEmpty() will always be O(1). I'd say use isEmpty().

Also see Jon Skeet's answer here: https://stackoverflow.com/a/11152624/342852

In Java8 you can use Optional to handle null cases properly. For example, both lists animalsNull and animalWithNullElements would be properly handled by the function filterList :

List<String> animalsNull = null;

List<String> animalWithNullElements = new ArrayList<String>();
        animalWithNullElements.add(0, null);
        animalWithNullElements.add(1, "Guybrush Threepwood");
        animalWithNullElements.add(2, null);

private static List<String> filterList(List<String> animals) {
        return Optional.ofNullable(animals)
               .orElseGet(Collections::emptyList)
               .stream()
               .filter(Objects::nonNull)
               .collect(Collectors.toList());
    }

It really depends on what you want to do. If you want to be sure that a list exist AND has some elements then you would use

if (list != null && !list.isEmpty())

If I may give some advice, while returning collections, return by default an empty collection. That way you will avoid nulls.

Number of times we have check condition like whether list is null or not.

For a start, a null collection and an empty collection are different things . If you need to test if a collection is null you need a different test to if you are trying to test if the collection is empty.

Secondly, if a collection could be either null or empty (and they "mean" the same thing, per your application design) then you have a problem in your design. You should most likely represent ... whatever it is you are trying to represent ... one way, and not either / both ways.

Thirdly, it is generally best to use an empty collection rather than a null , because you can treat an empty and non-empty collection uniformly. By contrast, a null always needs to be handled as a special case. (And if you forget to handle the null case, then you've got a potential for NullPointerExceptions .)


Having said that ...

Which is best condition or do we need to make some combination of these considering performance of program execution?

If you really need to deal with the case of a null , then you've no choice but to test for null .

For isEmpty() versus size() == 0 :

  • the two predicates should give the same answer (unless you have an infinite lazy collection ...), but

  • in some cases isEmpty() could be faster, at least in theory.

The latter depends on the implementation of the collection type: specifically, on whether the size() method needs to count the collection elements. (I don't think that any of the standard collection classes have this property, but that's not to say that you won't find some class that does ...)

So the optimal predicate is most likely either:

 c != null && !c.isEmpty()

or

 !c.isEmpty()

depending on whether you (really) need to cater for nulls.

And the obvious corollary is that your application is likely to be more efficient ... as well as simpler and more robust ... if you don't use null to represent empty collections. (If you need immutable empty collection objects, you can get them for free from methods / statics defined by the Collections class.)

There is a useful util class called CollectionUtils from Apache commons-collections bundle. With using it the code will look like:

if(CollectionUtils.isEmpty(collection))

It looks nice and under the hood it has the same invocation:

public static boolean isEmpty(Collection coll) { return coll == null || coll.isEmpty(); }

null means list is initialized with null. null list size or isEmpty will throw NullPointerException . But, not null list can be empty or size==0

(list!=null) != (list.size()==0)

size==0 and isEmpty is equivalent.

(list.size()==0) ==  list.isEmpty()

There can be multiple approaches to handle this:

1: If code makes sure that collection cannot be null by initializing it either in constructor or as field initializaiton then caller need not to ideally check for null everywhere. Only isEmpty check should suffice:

private List<Integer> numbers = new ArrayList<Integer>(); //or in constructor

// caller can then safely use

if(numbers.isEmpty)

2: Alternatively write a utility method to have null and empty check, no need for size check as it already happens inside isEmpty call. Use this utility method elsewhere in code.

public static boolean empty(Collection<?> col) {
   return col == null || col.isEmpty();
}

It depends on your program structure. For example, I have a helper class called ArrayUtils , in which I have an API that looks like this:

public static <E> boolean isEmpty(final Collection<E> collection)
{
    return collection == null || collection.isEmpty();
}

I use this one when I know that I may get a null list, but when I'm absolutely sure it's not null , I use only if ( collection.isEmpty ) . Improves code readability, too.

collection.size() > 1 is redundant, because you have the other APIs at your disposal.

If it you are owner of the codebase, I would avoid using such logic at all. Instead try to follow the model when your collection supplier can't return null but has a reference to Collections.emptyXXX or just regular empty container empty.

You can do it with two predicates as below :

public static final Predicate<String> NULL_OR_EMPTY = (in) -> null == in || "".equals(in);

public static final Predicate<List<String>> STRING_LIST_NULL_OR_EMPTY = (strList) ->  strList.stream().filter(NULL_OR_EMPTY).collect(Collectors.toList()).size() > 0;

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