Which of the 2 is better from a processing or optimizing point of view?
I feel Option 1 is more readable, but I've been told Option 2 is more efficient. Is that so?
if (value != null) {
if (value.equalsIgnoreCase(ApplicationConstants.A)) {
} else if (value.equalsIgnoreCase(ApplicationConstants.B)) {
}
}
Option 2:
if ((value != null) && (value.equalsIgnoreCase(ApplicationConstants.A))) {
} else if ((value != null) && (value.equalsIgnoreCase(ApplicationConstants.B))) {
}
There's nothing here to care about performance wise, write your code so it's as readable as you can make it.
When performance testing later highlights areas that need to be optimized then and only then optimize only the places that need it.
To make it more readable you can invert your tests to get rid of the null check:
if (ApplicationConstants.A.equalsIgnoreCase(value)) {
} else if (ApplicationConstants.B.equalsIgnoreCase(value)) {
}
Option 1 is efficient since there is no redundant null check.
I'd expect the first to be slightly more efficient, because && is short-circuit, so it gives multiple conditional branches anyway. But if you want to be certain, time them.
I would go with option 1 as in option 2, more no of comparisons are made.
The first option is better as with one condition check you can decide.
so if value != null then only it will enter else it will not even enter the conditional block.
But in 2nd option it will check if condition , and if false also it wd check else condition (for value == null).
Related
I'm running my code on sonarqube, but it shows there's an issue with my code, saying"Merge this if statement with the enclosing one." I tried it, but still have no idea how to solve it.
if (splitStrings.length == 2) {
if (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1) {
throw new IllegalArgumentException("Invalid Input");
}
}
You could do three things:
Either you need to chain the conditions as below:
if (splitStrings.length == 2
&& (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
You could declare local variable for Integer.parseInt(splitStrings[1]) inside the first if after adding the matches condition in it.
if (splitStrings.length == 2 && splitStrings[1].matches("\\d{1,3}")) {
int val = Integer.parseInt(splitStrings[1]);
if (val > 100 || val < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
}
Even though i won't recommend it, you could also suppress the warning using //NOSONAR in the line in which warning is displayed or add #SuppressWarnings("squid:S1066") at the method level.
Try this.
if (splitStrings.length == 2
&& (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
You should merge them by && between them and wrap the second with brackets, like:
if(splitStrings.length == 2 && (!splitStrings[1].matches("\\d{1,3}") || Integer.parseInt(splitStrings[1]) > 100 || Integer.parseInt(splitStrings[1]) < 1)){
//code here
}
Integer.parseInt may be skipped altogether if a better regexp is provided to check for the digits in the range [1..100], thus the conditions could be simplified:
if (splitStrings.length == 2 && !splitStrings[1].matches("(?!0)\\d{1,2}|100")) {
throw new IllegalArgumentException("Invalid Input");
}
Online demo of the regexp: (?!0)\d{1,2}|100 validating positive cases 0 < x <= 100
(?!0)\d{1,2} - 1 or 2 digit numbers except 0 excluded with negative lookahead (?!0): 1 - 99
|100 - OR 100
In my opinion the assertion that combining if statements makes code more readable is flawed. Often it makes sense to ask a series of questions in sequence, especially when each part is asking an essentially independent question.
This can (in direct opposition of the SonarQube assertion) make each part more readable. It also allows for correct placement of useful comments in cases where the meaning is not stupidly obvious.
Another valid reason for nested if statements would be to follow certain easily recognized coding patterns. An example would be in ASP.Net applications where Page_Load methods may often have an if (!PostBack) block, which can then contain additional logic that may include additional nested conditions. If there is only one nested condition and it is combined, later changes may need to undo that merge. (There may be a case at that point for refactoring the logic into a separate method at that point, but that is a different subject.)
The question of whether or not to combine nested if statements should be left to the discretion and good judgement of the author (and code reviewer) based on which form is more readable and/or maintainable.
In your particular case, your logic is asking two questions: (1) "Does the input have two parts?" and (2) "Is the second part valid"?
So yes, your nested if statements can be combined into a single (but logically more complex) statement, but this is not necessarily better.
I have an int, int minion1Hp, which can be a value of 0 -> 20. Depending on the value it is, a certain image resource will be set for an ImageView, using bar1.setImageResource(R.drawable.hpa);. However, my code currently looks like this:
if (minion1Hp == 0) {
bar1.setImageResource(R.drawable.hp);
}
if (minion1Hp == 1) {
bar1.setImageResource(R.drawable.hpa);
}
if (minion1Hp == 2) {
bar1.setImageResource(R.drawable.hpb);
}
if (minion1Hp == 3) {
bar1.setImageResource(R.drawable.hpc);
}
if (minion1Hp == 4) {
bar1.setImageResource(R.drawable.hpd);
}
if (minion1Hp == 5) {
bar1.setImageResource(R.drawable.hpe);
}
... and so on. Is there a more efficient way of doing this, rather than a long list of if statements?
Suggestion: initialize a map at startup (say in onCreate()). Like this:
mDrawables = new HashMap<Integer, Integer>();
mDrawables.put(0, R.drawable.hp);
mDrawables.put(1, R.drawable.hpa);
...
then just do:
bar1.setImageResource(mDrawables.get(minion1Hp));
You can use a switch statement with a separate case for each instance. On a side note, you shouldn't be using just if statements up there, your code will run slowly, you should be using else if to make it run faster (since your hp can never be 1 and 2 at the same time.
Ex for switch statements:
switch (minion1Hp){
case 1:
bar1.setImageResource(R.drawable.hp);
break;
case 2:
bar1.setImageResource(R.drawable.hpa);
break;
etc.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
An improvement here would be to change each if after the first one to an else if as minion1Hp can't be multiple values at the same time, but you might find it slightly neater to have the whole thing in a switch-case block instead.
I'm getting some peculiar output from a program in which I have a few if statements like this:
if((m.getLeft(position).state == position.state.wall || m.getLeft(position).state == position.state.border)
&& (m.getBelow(position).state == position.state.open || m.getBelow(position).state == position.state.visited)){
check = true;
}
where I have both && and || used in the same if condition. I want the boolean check to be made true if the cell at getLeft() is either a wall or a border AND the cell at getBelow() is either open or visited.
Does this code, the way I have it written now, perform this check properly? Perhaps more importantly, is it poor form to write a statement like this? Would it be better to break it up into two statements?
I'm not sure whether the peculiarities I'm seeing are resulting from these statements or something else, my question is more about general best practices.
EDIT: Thanks for all the input. I suspected as much (that it was too complicated), which was why I framed my question the way I did.
EDIT (a year later, looking back) (to restate the above more strenuously) for the love of god, don't write anything like the if statement above. If you find yourself with a similar line of code, remember occam's razor is perhaps nowhere more applicable than in programming.
Your complicated if statement can be refactored as:
if((m.getLeft(position).state == position.state.wall || m.getLeft(position).state == position.state.border)) {
if((m.getBelow(position).state == position.state.open || m.getBelow(position).state == position.state.visited)){
check = true;
}
}
Thanks to #Makoto:
check = ((m.getLeft(position).state == position.state.wall || m.getLeft(position).state == position.state.border)) && ((m.getBelow(position).state == position.state.open || m.getBelow(position).state == position.state.visited));
And your code, as well as this code "works".
But also, remember, stick to a naming convention that is mentioned in Java's Style Guidelines. I have no idea what m in your code is. This kind of naming an object reference must be avoided. Also, state seems to be a public field in your class (assuming). Such public access fields should also be avoided. Instead use getters() and setters().
It looks to me that it performs properly, however it is rather difficult to read.
If you're going to be using an && in an if statement, you may as well nest a new if statement instead, it is essentially the same thing in most cases.
Breaking down your boolean statement, it reads something like this:
(a == x_1 || a == x_2) && (b == x_3 || b == x_4)
Unfortunately, that's about as simple as that particular boolean statement will get. There are options to make the pain a lot easier:
Refactor your code to not need such complex statements, by breaking it up into two if-blocks (as shown in my refactor below), or
Extract that as a method and assign the return value to check. Honestly, it's either going to be true or false.
Here's an example of the refactor method. I don't know what m is precisely:
public boolean isCheck(M m, Position p) {
boolean retVal = false;
if(m.getLeft(p).state == p.state.wall || m.getLeft(p).state == p.state.border)) {
if((m.getBelow(p).state == p.state.open || m.getBelow(p).state == p.state.visited))
retVal = true;
}
}
return retVal;
}
// call it as such
check = isCheck(m, position);
Use another IF insted of using &&:
if(m.getLeft(position).state == position.state.wall ||
m.getLeft(position).state == position.state.border){
if(m.getBelow(position).state == position.state.open ||
m.getBelow(position).state == position.state.visited){
check = true;
}
}
I am writing a method, and would like to know if the attached code is efficient depending on how it is written:
public boolean isThreeOfKind(PlayingCard[] hand)
{
// if(hand[0].getRank() == hand[2].getRank())
// return true;
// else if(hand[1].getRank() == hand[3].getRank())
// return true;
// else if(hand[2].getRank() == hand[4].getRank())
// return true;
return (hand[0].getRank() == hand[2].getRank() ||
hand[1].getRank() == hand[3].getRank() ||
hand[2].getRank() == hand[4].getRank());
}
So as you can see I have an if else if statement commented out, and a return statement doing the same thing basically, which would be more efficient and according to coding standards?
No difference in efficiency, but definite difference in style, the second one being much better. However, this particular logic is really just
for (int i = 0; i < 3; i++)
if (hand[i].getRank() == hand[i+2].getRank()) return true;
return false;
This type of question might be better on CodeReview because it's more of an opinion. But In my opinion it's much easier to read the non-commented portion and performance shouldn't be worried about until it becomes an issue (especially in something like this). For more on that see the Program optimization article on Wikipedia particularly the When to Optimize section.
As Jeffery said, I'd say readability is more valuable than efficiency in this case (I wouldn't say that's a universal rule).
You might be interested in a concept called Short-Circuit Evaluation. Notice that || is a short-circuit operator in Java. As such, you'll get the same effect as the if statements if the first statement is true (the other two will not be evaluated).
That being said, I'm not sure if those two bits of code compile down into the same function (they might depending on the compiler implementation). If they do not compile down the same, the second will likely be faster.
Or if you prefer only one exit point in the method and array boundary checking:
boolean found = false;
for (int i = 0; !found && i < hand.length - 2; i++)
found = (hand[i].getRank() == hand[i + 2].getRank());
return found;
Lots of Java books describe the switch statement as being faster than the if else statement. But I did not find out anywhere why switch is faster than if.
Example
I have a situation I have to choose any one item out of two. I can use either use
switch (item) {
case BREAD:
//eat Bread
break;
default:
//leave the restaurant
}
or
if (item == BREAD) {
//eat Bread
} else {
//leave the restaurant
}
considering item and BREAD is a constant int value.
In the above example which is faster in action and why?
Because there are special bytecodes that allow efficient switch statement evaluation when there are a lot of cases.
If implemented with IF-statements you would have a check, a jump to the next clause, a check, a jump to the next clause and so on. With switch the JVM loads the value to compare and iterates through the value table to find a match, which is faster in most cases.
A switch statement is not always faster than an if statement. It scales better than a long list of if-else statements as switch can perform a lookup based on all the values. However, for a short condition it won't be any faster and could be slower.
The current JVM has two kinds of switch byte codes: LookupSwitch and TableSwitch.
Each case in a switch statement has an integer offset, if these offsets are contiguous (or mostly contiguous with no large gaps) (case 0: case 1: case 2, etc.), then TableSwitch is used.
If the offsets are spread out with large gaps (case 0: case 400: case 93748:, etc.), then LookupSwitch is used.
The difference, in short, is that TableSwitch is done in constant time because each value within the range of possible values is given a specific byte-code offset. Thus, when you give the statement an offset of 3, it knows to jump ahead 3 to find the correct branch.
Lookup switch uses a binary search to find the correct code branch. This runs in O(log n) time, which is still good, but not the best.
For more information on this, see here: Difference between JVM's LookupSwitch and TableSwitch?
So as far as which one is fastest, use this approach:
If you have 3 or more cases whose values are consecutive or nearly consecutive, always use a switch.
If you have 2 cases, use an if statement.
For any other situation, switch is most likely faster, but it's not guaranteed, since the binary-search in LookupSwitch could hit a bad scenario.
Also, keep in mind that the JVM will run JIT optimizations on if statements that will try to place the hottest branch first in the code. This is called "Branch Prediction". For more information on this, see here: https://dzone.com/articles/branch-prediction-in-java
Your experiences may vary. I don't know that the JVM doesn't run a similar optimization on LookupSwitch, but I've learned to trust the JIT optimizations and not try to outsmart the compiler.
So if you plan to have loads of packets memory isn't really a large cost these days and arrays are pretty fast. You also cannot rely on a switch statement to auto generate a jump table and as such it's easier to generate the jump table scenario yourself. As you can see in below example we assume a maximum of 255
packets.
To get the below result your need abstraction.. i'm not going to explain how that works so hopefully you have an understanding of that.
I updated this to set the packet size to 255 if you need more then that you'll have to do a bounds check for (id < 0) || (id > length).
Packets[] packets = new Packets[255];
static {
packets[0] = new Login(6);
packets[2] = new Logout(8);
packets[4] = new GetMessage(1);
packets[8] = new AddFriend(0);
packets[11] = new JoinGroupChat(7); // etc... not going to finish.
}
public void handlePacket(IncomingData data)
{
int id = data.readByte() & 0xFF; //Secure value to 0-255.
if (packet[id] == null)
return; //Leave if packet is unhandled.
packets[id].execute(data);
}
Edit since I use a Jump Table in C++ a lot now i'll show an example of a function pointer jump table. This is a very generic example, but I did run it and it works correctly. Keep in mind you must set the pointer to NULL, C++ will not do this automatically like in Java.
#include <iostream>
struct Packet
{
void(*execute)() = NULL;
};
Packet incoming_packet[255];
uint8_t test_value = 0;
void A()
{
std::cout << "I'm the 1st test.\n";
}
void B()
{
std::cout << "I'm the 2nd test.\n";
}
void Empty()
{
}
void Update()
{
if (incoming_packet[test_value].execute == NULL)
return;
incoming_packet[test_value].execute();
}
void InitializePackets()
{
incoming_packet[0].execute = A;
incoming_packet[2].execute = B;
incoming_packet[6].execute = A;
incoming_packet[9].execute = Empty;
}
int main()
{
InitializePackets();
for (int i = 0; i < 512; ++i)
{
Update();
++test_value;
}
system("pause");
return 0;
}
Also another point i'd like to bring up is the famous Divide and Conquer. So my above 255 array idea could be reduced to no more then 8 if statements as a worst case scenario.
I.e. but keep in mind it get's messy and hard to manage fast and my other approach is generally better, but this is utilize in cases where arrays just won't cut it. You have to figure out your use case and when each situation works best. Just as you wouldn't want to use either of these approaches if you only have a few checks.
If (Value >= 128)
{
if (Value >= 192)
{
if (Value >= 224)
{
if (Value >= 240)
{
if (Value >= 248)
{
if (Value >= 252)
{
if (Value >= 254)
{
if (value == 255)
{
} else {
}
}
}
}
}
}
}
}
At the bytecode level, subject variable is loaded only once into processor register from a memory address in the structured .class file loaded by Runtime,and this is in a switch statement; whereas in an if-statement, a different jvm instruction is produced by your code-compiling DE, and this requires that each variable be loaded in to registers although same variable is used as in next preceeding if-statement. If you know of coding in assembly language then this would be commonplace; although java compiled coxes are not bytecode, or direct machine code, the conditional concept hereof is still consistent.
Well, I tried to avoid deeper technicality upon explaining. I hope I had made the concept clear and demystified. Thank you.