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)
{...
david_p
  • 223
  • 1
  • 6
  • 17
  • 1
    the second method calls getContainers just once so it's better performance – Ali Baghdadi Nov 06 '15 at 13:20
  • 1
    Add simple System.out.println() to the getContainers() and you will see the result =) For me second variant better. – Lugaru Nov 06 '15 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. – CosmicGiant Nov 06 '15 at 13:23
  • A better solution is to change `getContainers()` to return a `Collections.emptyList()` instead of `null`. – Peter Lawrey Nov 06 '15 at 14:33

3 Answers3

4

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.
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
  • Note that the possibility mentioned in the second point would prohibit the optimization by the compiler mentioned in the first point. – skyking Nov 06 '15 at 13:26
  • @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. – Eugen Rieck Nov 06 '15 at 13:28
  • 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. – skyking Nov 06 '15 at 13:52
  • I would expect this sort of optimization to happen at JIT time (if at all). At that point, the info is available. – Eugen Rieck Nov 06 '15 at 14:12
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).

skyking
  • 13,817
  • 1
  • 35
  • 57
  • 1
    Since your answer talks about micro-optimization, you might want to include [this](http://stackoverflow.com/questions/1923795/java-method-invocation-vs-using-a-variable) link :) – sam Nov 06 '15 at 13:26
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.

ergonaut
  • 6,929
  • 1
  • 17
  • 47