Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java performance vs. code-style: Making multiple method calls from the same line of code

I am curious whether packing multiple and/or nested method calls within the same line of code is better for performance and that is why some developers do it, at the cost of making their code less readable.

E.g.

//like
Set<String> jobParamKeySet = jobParams.keySet();
Iterator<String> jobParamItrtr = jobParamKeySet.iterator();

Could be also written as

//dislike    
Iterator<String> jobParamItrtr = jobParams.keySet().iterator();

Personally, I hate the latter because it does multiple evaluations in the same line and is hard for me to read the code. That is why I try to avoid by all means to have more than one evaluation per line of code. I also don't know that jobParams.keySet() returns a Set and that bugs me.
Another example would be:

//dislike
Bar.processParameter(Foo.getParameter());

vs

//like
Parameter param = Foo.getParameter();
Bar.processParameter(param);

The former makes me noxious and dizzy as I like to consume simple and clean evaluations in every line of code and I just hate it when I see other people's code written like that.

But are there any (performance) benefits to packing multiple method calls in the same line?

EDIT: Single liners are also more difficult to debug, thanks to @stemm for reminding

like image 731
amphibient Avatar asked Oct 09 '12 14:10

amphibient


3 Answers

Micro optimization is killer. If the code references you are showing are either instance scope (or) method scope, I would go with second approach.

Method scope variables will be eligible for GC as soon as method execution done, so even you declare another variable, it's ok because scope is limited and the advantage you get will be readable and main-table code.

like image 170
kosa Avatar answered Oct 15 '22 21:10

kosa


I tend to disagree with most others on this list. I actually find the first way cleaner and easier to read.

In your example:

//like
Set<String> jobParamKeySet = jobParams.keySet();
Iterator<String> jobParamItrtr = jobParamKeySet.iterator();
Could be also written as

//dislike    
Iterator<String> jobParamItrtr = jobParams.keySet().iterator();

the first method (the one you like) has a lot of irrelevant information. The whole point of the iterator interface, for example, is to give you a standard interface that you can use to loop over whatever backing implementation there is. So the fact that it is a keyset has no bearing on the code itself. All you are looking for is the iterator to loop over the implemented object.

Secondly, the second implementation actually gives you more information. It tells you that the code will be ignoring the implementation of jobParams and that it will only be looping through the keys. In the first code, you must first trace back what jobParamKeySet is (as a variable) to figure out what you are iterating over. Additionally, you do not know if/where jobParamKeySet is used elsewhere in the scope.

Finally, as a last comment, the second way makes it easier to switch implementations if necessary; in the first case, you might need to recode two lines (the first variable assignment if it changes from a set to something else), whereas the second case you only need to change out one line.

That being said, there are limits to everything. Chaining 10 calls within a single line can be complicated to read and debug. However 3 or 4 levels is usually clear. Sometimes, especially if an intermediary variable is required several times, it makes more sense to declare it explicitly.

In your second example:

//dislike
Bar.processParameter(Foo.getParameter());
vs

//like
Parameter param = Foo.getParameter();
Bar.processParameter(param);

I find it actually more difficult to understand exactly which parameters are being processed by Bar.processParameter(param). It will take me longer to match param to the variable instantiation to see that it is Foo.getParameter(). Whereas the first case, the information is very clear and presented very well - you are processing Foo.getParameter() params. Personally, I find the first method is less prone to error as well - it is unlikely that you accidentally use Foo2.getParamter() when it is within the same call as opposed to a separate line.

like image 5
Eric B. Avatar answered Oct 15 '22 21:10

Eric B.


There is one less variable assignment, but even the compiler can optimize it in some cases. I would not do it for performance, it is kind of an early optimization. Write the code that is easier to maintain.

In my case, I find:

Iterator<String> jobParamItrtr = jobParams.keySet().iterator();

easier to be read than:

Set<String> jobParamKeySet = jobParams.keySet();
Iterator<String> jobParamItrtr = jobParamKeySet.iterator();

But I guess it is a matter of personal taste.

like image 3
Guido Avatar answered Oct 15 '22 22:10

Guido