0

I know this is simple but I couldn't find any question on it.

When I check if a list is null and then iterate over it, how it affects on performance?

I have the following code and I wonder if the second call to getContainers() perform the method again or the compiler is saving the list so it don't have to run getContainers() again.

if (getContainers() != null)
{
    for (Container container : getContainers())
{...

if this is not true I was thinking of doing something like this code below but it seems to naive.

List<Container> listC = getContainers();
if (listC != null)
{
    for (Container container : listC)
{...
4
  • 1
    the second method calls getContainers just once so it's better performance Commented Nov 6, 2015 at 13:20
  • 1
    Add simple System.out.println() to the getContainers() and you will see the result =) For me second variant better. Commented Nov 6, 2015 at 13:22
  • Checking if an object is null has practically no hit on performance. The second method will have a better performance because it doesn't repeat the operations done within the getContainers() method; in other words, it gets (or fails to get, in case of a null result) the list just once; but this has nothing to do with the performance impact of the check for null itself. Commented Nov 6, 2015 at 13:23
  • A better solution is to change getContainers() to return a Collections.emptyList() instead of null. Commented Nov 6, 2015 at 14:33

3 Answers 3

5

The 2nd version is much better for two reasons:

  • Not so important: The performance advantage you mentioned, if it is not automatically optimized into by the compiler
  • More important: If run in a multithreaded environment, the two calls to getContainers() might not give the same result: The first one might not be null, but the second one might be.
Sign up to request clarification or add additional context in comments.

4 Comments

Note that the possibility mentioned in the second point would prohibit the optimization by the compiler mentioned in the first point.
@skyking: Not necessarily. I don't know a lot about the Java compiler, but I do know that other compilers make different optimizations depending on the absence or presence of multithreading. What I thought of was future use of code created for a singlethreaded environment may create hard to find bugs.
OK, but can a Java compiler really determine that at compile time? I mean if it compiles it to a .class file and then the .class file is used together with some other .class file that actually starts new threads it would be a problem if the first assumed that the second shouldn't create threads.
I would expect this sort of optimization to happen at JIT time (if at all). At that point, the info is available.
2

It's likely that it will call the getContainers function twice. Unless it's known that it couldn't be overridden and therefore could be concluded that it will have no side effects and return the same value.

Therefore it's a reasonable to do it as your second example shows. However note that it will only be called twice and that should normally not be good enough reason to try this optimization.

Before you try to optimize you should actually measure how much time the code takes before and after optimization. Before because it would tell you if there's need to optimize, and after in order to see that you've actually optimized (I've seen a few "optimization" that increased execution time).

1 Comment

Since your answer talks about micro-optimization, you might want to include this link :)
0

The question is confusingly stated. The fact is, you need to check if getContainers() returns null at some point, unless you will allow the NullPointerException, which in this case, you decided not to take the chance. In both examples, you are checking for null, so this operation takes exactly the same time.

What you are really interested in, is whether writing getContainers() twice will affect performance. If you understand that this method does not do anything more than return a stored object in the (perhaps private) local class, then you shouldn't worry about any performance as it would be unnoticeable. If it does do something more complex but could be cached by the other method, then you should look into the other method. It might not this method's fault for calling it twice. If in doubt, the second example guarantees it is only called once at the cost of declaring a variable for it.

It's also important to note that in the enhanced for loop,

for (Container container : getContainers() )

the getContainers() is only called once, and not every iteration of the for loop. It retrieves the list internally and gets an iterator from it which assigns a value to container each iteration. The only problem is that it doesn't check for NPEs.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.