Will there be any performance difference in following code? - java

I want to know whether there is a performance difference in following two code blocks
1>
if(name == null) {
//something
}
if(name != null) {
//something
}
and
2>
if(name == null) {
//something
}
else {
//something
}

The first compares twice, the second compares once. The difference will not be noticeable, but it's there.

after benchmarkint it on 100.000.000 iterations, the first execution costs 719ms and the second 703ms.
I used a modulo so the conditions has to change every turn and avoid precompiled result. Please find the code below. I have noticed that this gap reduces when number of iterations increases.
public static void main(String[] args) {
Date start1 = new Date();
for(int i=0; i<100000000; i++) {
int it = i%2;
if(it == 0) {
double j = Math.random();
j++;
}
if(it != 0) {
double j = Math.random();
j++;
}
}
Date end1 = new Date();
Date start2 = new Date();
for(int i=0; i<10000000; i++) {
int it = i%2;
if(it == 0) {
double j = Math.random();
j++;
} else {
double j = Math.random();
j++;
}
}
Date end2 = new Date();
System.out.println((end1.getTime()-start1.getTime())+" / "+(end2.getTime()-start2.getTime()));
}

Just a brief comment to say that the compiler cannot optimize it in all cases, because name is visible within the first if block therefore it could have been modified in it, so it has to be checked again in the second if condition. Imagine this case:
if (name == null) {
// Does something
name = "Did it.";
}
if (name != null) {
// Does something else
}
It's clearly not equivalent to
if (name == null) {
// Does something
name = "Did it.";
} else {
// Does something else
}
If what you actually mean is that you should do something in one case and something else otherwise, please use if { ... } else { ... } - not just for (minimal) performance improvement, but also because your code should reflect what you actually mean.

Note that the two fragments are not necessarily equivalent, because the first block could re-assign name so that the second condition will also be true.
This can introduce hard to spot bugs, so I suggest that (before thinking about performance), you think about making the variable final if possible and use if/else when it makes sense (i.e. it should enter only one of the two branches) and chained if's when that makes sense (for example when the first if can establish a default value for the next one to use).

Yes there will, on the second one only one condition will be checked and on the first one two conditions would have to be checked.
An if clause that fails its evaluation has to make an "instruction jump" even if there is no else statement follwing it.
Assuming the first if is false, you'd be comparing these 2 execution scenarios:
1>
Check 1st condition
Skip to check 2nd condition
Do "something" inside the 2nd condition
2>
Check condition
Skip to "something" inside the else

Yes becuase both if cases will be evaluated in the first whereas only one if will be evaluated in the second.

yes, there will be a difference: in the second example, tehre's only 1 statement to be proofed, in the first one there are two.
but: the difference in performance will be absolutely minimal, in 99% of the cases you won't even notive any difference - make sure your code is as readable as it can be, thats much more important ;)

yes obviously the second code will perform inconsiderably better, because there is only one condition to check

I believe the compiler is smart enough to notice that the second if in the first example is redundant, so there won't be any performance change

Related

Compilation error in BlueJ- if else with return statement

I am using BlueJ IDE to write java programs.
I have a method with String return type. I have put the return statements within if-else, such that if the boolean variable "flag" has true value, then one value is returned, while if the value is false, another value is returned.
Now, the problem is that BlueJ asks for another return statement even after this, as shown below.
If I give another return after if-else, it works.
Why is this happening? I had learnt that there can be no statements after the return statement. So, why is the compiler asking for another return statement?
If someone wants the code for cut-paste purposes, here it is. This code is meant to convert binary numbers to their decimal equivalents, including fractions, but no negative numbers.
public class Conversions{
protected String Binary_Decimal(String str){
int a = str.indexOf('.');
boolean flag = false;
if (a == -1){
str += ".0";
a = str.indexOf('.');
flag = true;
}
String bd = str.substring(0, a);
String ad = str.substring(a + 1);
a = 0;
double num = 0;
for (int i = bd.length() - 1; i >= 0; i--){
num += Math.pow(2, a) * Integer.parseInt(Character.toString(str.charAt(i)));
a++;
}
if (flag == true){
return Integer.toString((int) num);
}
else if (flag == true) {
a = -1;
for (int i = 0; i < ad.length(); i++){
num += Math.pow(2, a) * Integer.parseInt(Character.toString(str.charAt(i)));
a--;
}
return String.valueOf(num);
}
return String.valueOf(num); //<-- WHY DOESN'T IT RUN WITHOUT THIS EXTRA return?
}
}
Here, str is the string that is input by the user using a different method Input().
The issue is that you wrote an if - else as an if - else if. The compiler does not understand or care that the two conditions you have are mutually exclusive and therefore cover all cases. Given how you wrote the branches, you need an explicit else or a catchall return for the compiler to be assured that the function always returns a String.
This is one example of why it is a bad idea to explicitly spell out the else when you have a set of conditions. The more important reason being that your if will often contain something much more complex and you might not negate it properly.
Delete the second ELSE IF clause and put the block directly after the first return statement, and consider that flag is a boolean. As follows:
if (flag) return Integer.toString((int) num);
a=-1;
for(....){
....
}
return String.valueOf(num);
In this way, the compiler should not notify you that error.
So, why is the compiler asking for another return statement?
Because you are missing a default return statement.
What if none of the conditions you have satisfied ? There must be something return default right ? That is what the issue is. That is why it is getting compiled when you uncomment that line.
Or even , you have an else statement, your program will have at least one satisfied return and it gets compiled too. Try it.
I had learnt that there can be no statements after the return statement.
This statement comes with some conditions. You have the return statement inside the if condition. So if your expression is not true, there is no way that the return gets execute.

Updating the value of a variable from the outer scope within an if block

int i = 3;
int j = 2;
int k = 1;
Printer printer = new Printer();
if (printer.getTotalAmount() > 0) {
if (printer.getType().equals("canon")) {
if (i >= j) {
i = i-j; // i=3-2, so i will be 1 now
}
}
if (printer.getType().equals("epson")) {
if (i >= k) {
i = i - k; // it should be i = 1-1 and i will be 0 now
}
}
}
My problem is that the variable i's value is not updated after the previous if statement. Due to block scope, the variable i's value is still 3.
How can I solve this problem?
Your two if statements represent mutually-exclusive conditions. The printer's type can be "canon" OR it can be "epson". Never both. So only one of your two if conditions will be met, and only one of the two code blocks will be executed.
Say, for example, that your Printer's type is "epson". When the first condition is evaluated, it will check whether "epson" is equal to "canon". Since they are not equal, the condition evaluates to false and all of the code inside of your if () {/* code */} block is completely skipped.
Your theory behind the scope causing the issue isn't accurate: since the variable is declared outside of the if block, the updated value will be reflected in every location that has access to that variable.
You need to update your logic to account for the fact that only one of the scenarios will occur or, if this is just a code simplification, find a more appropriate scenario analogous to your real code.
It may be helpful to review Oracle's tutorial on the if statement if this still isn't clear.
I think you should add debug statements to know more about flow of your program
becuase you didn't mention the value of printer.getTotalAmount() and printer.getType()
on which value of i is depend.
e.g.
System.out.println("Total Amount:"+ printer.getTotalAmount());
if (printer.getTotalAmount() > 0) {
System.out.println("Type:"+ printer.getType());
if (printer.getType().equals("canon")) {
System.out.println("inside if canon");
if (i >= j) {
i = i-j; // i=3-2, so i will be 1 now
}
}
if (printer.getType().equals("epson")) {
System.out.println("inside if epson");
if (i >= k) {
i = i - k; // it should be i = 1-1 and i will be 0 now
}
}
}

In Java, when is a "do while" loop the only option?

Is there ever a situation where you must use a do while loop? Is it an accepted practice? It seems like it is equivalent to a plain while loop except that its first iteration happens before checking the conditional, if that is even true.
int i = 3;
while ( i > 0 ) { // runs 3 times
i--;
}
vs
int j = 3;
do {
j --;
} while ( j > 0 ); // runs 3 times
The same?
EDIT: I have seen the java doc, but
the example in the java docs doesn't look like it requires that the particular routine inside of the do while loop must be run in the do while loop instead of inside of a regular while loop!
Is there ever a situation where you must use a do while loop?
No: every do-while loop can be written as a while-loop by running the body once before the loop begins. However, there are certainly cases where it makes more sense to use the do-while construct (i.e. if you always want the loop to iterate at least once), which is why it exists in the first place.
Is it an accepted practice?
If you use it appropriately, then yes absolutely.
It seems like it is equivalent to a plain while loop except that its first iteration happens before checking the conditional, if that is even true.
That's right. You can read more about do-while in its tutorial.
This example maybe help you be clearer:
int i = 3;
System.out.print("while: ");
while (--i > 0){
System.out.print("x");
}
System.out.print("\ndo-while: ");
int j = 3;
do
{
System.out.print("x");
}while (--j > 0);
This prints
while: xx
do-while: xxx
A real time example.
There is a contest with 5 level.
In each level if you score 100 you can proceed to next level.
Less code for do while, but not for while.
boolean playContest()
{//do while
int level = 1;
int score;
do
{
score = 0;
score = play();
}while(score>99 && level++<6)
if(level>4 && score>99)
isWinner = true;
else
isWinner = false;
return isWinner;
}
boolean playContest()
{//while
int level = 1;
int score;
while(level <6)
{
score = 0;
score = play();
if(score < 100)
break;
level++;
}
if(level>4 && score>99)
isWinner = true;
else
isWinner = false;
return isWinner;
}
basic difference between while and do-while is do while will be executed at least once.
when do-while is best option?
in case when you want to execute some actions till you meet condition, of course you could achieve same thing by using while but early termination of loop with break, is nasty and ugly solution
When you want to execute the statement inside do for at least once, then you can go for it.
Directly from Docs
The difference between do-while and while is that do-while evaluates its expression at the bottom of the loop instead of the top. Therefore, the statements within the do block are always executed at least once,
do {
statement(s)
} while (expression);
No, there is no time a do-while loops is the only option, it is used for convenience when you do not want to repeat code.

Changing recursive method to iterative

i have recrusive function which works fine. The problem is it gives stackoverflow error when the number of lines are huge. I want to put it in iterative, probably using a for loop. Need some help in doing it.
private TreeSet validate(int curLine, TreeSet errorSet) {
int increment = 0;
int nextLine = 0;
if (curLine == lines.length || errorSet.size() != 0) {
return errorSet;
} else {
String line = lines[curLine];
//validation starts. After validation, line is incremented as per the requirements
increment = 1 //As per requirement. Depends on validation results of the line
if (increment > 0) {
try{
Thread.currentThread().sleep(100);
}catch(Exception ex){
System.out.println(ex);
}
nextLine = (curLine + increment);
validate(nextLine, errorSet);
}
}
return errorSet;
}
Poster's description of the method:
The method does validates textlines, these lines has instructions of how much line has to be skipped, if the line is valid. So, if the line is valid that many of lines will be skipped using the increment. if the line is not valid increment will be 0.
I'm not sure why this was ever recursive in the first place. This is perfectly suited for the use of a FOR loop. use something like so:
private TreeSet validate(int curLine, TreeSet errorSet) {
int increment = 0;
if (errorSet.size() != 0)
return errorSet;
for (int curLine = 0; curLine < lines.Length; curLine += increment)
{
// put your processing logic in here
// set the proper increment here.
}
}
If the increment is always going to be 1, then you can just use curr++ instead of curLine += increment
for(String line : lines) {
// validate line here
if(!errorSet.isEmpty()) {
break;
}
}
The solution for your problem could be simple for loop or while, with logical expression for stop condition. Typically we use for loop when we have to pass through all elements of Iterable or array. In case when we are not aware how many loops we are going to do we use a while loop. Advantage of for loop over while, is that we for free have localized variables so we ca not use them out side of the loop, therefore we reduce possibility to have some bug.
You problem is that you have to break the program on two conditions:
When errorSet is not empty.
When the array of lines have no longer items.
As contradiction, we can say that your program should continue:
Until errorSet is empty,
and until line number is smaller than array size where they are stored.
This provide us to simply expression
errorSet.isEmpty()
lineNumber < lines.length()
We can combine them using logical operator && and use as a stop rule in for loop.
for(int lineNumber= 0; errorSet.isEmpty() && lineNumber< lines.length(); lineNumber++) {
//code to operate
}
Note:
Typically for logical expression is used operator &&, that assure that every part of the logical expression is evaluated. An alternative for this is &, that in case of false do not operate longer and return false. We could be tempted to use this operator for this expression but i would be bad idea. Because when we would traversed all lines without error code will generate IndexOutOfBoundException, if we switch the places then we would not have any optimization as first expression would be evaluated same number of times.

How can I remove the while(true) from my loop in Java?

I've heard that using while(true) is a bad programming practice.
So, I've written the following code to get some numbers from a user (with default values). However, if the user happens to type in -1, then it will quit the program for them.
How should this be written then without a while(true)? I can think of a condition to make the while loop go off that will get caught right away without continuing on until the next iteration?
Here is how I have it now:
public static void main(String[] args)
{
System.out.println("QuickSelect!");
while (true)
{
System.out.println("Enter \"-1\" to quit.");
int arraySize = 10;
System.out.print("Enter the size of the array (10): ");
String line = input.nextLine();
if (line.matches("\\d+"))
{
arraySize = Integer.valueOf(line);
}
if (arraySize == -1) break;
int k = 1;
System.out.print("Enter the kth smallest element you desire (1): ");
line = input.nextLine();
if (line.matches("\\d+"))
{
k = Integer.valueOf(k);
}
if (k == -1) break;
List<Integer> randomData = generateRandomData(arraySize, 1, 100);
quickSelect(randomData, k);
}
}
while (true) is fine. Keep it.
If you had a more natural termination condition, I'd say to use it, but in this case, as the other answers prove, getting rid of while (true) makes the code harder to understand.
There is a Single Entry Single Exit (SESE) school of thought that suggests that you should not use break, continue or abuse exceptions to do the same for some value of abuse). I believe the idea here is not that you should use some auxiliary flag variable, but to clearly state the postcondition of the loop. This makes it tractable to formerly reason about the loop. Obviously use the stands-to-reason form of reasoning, so it is unpopular with the unwashed masses (such as myself).
public static void main(String[] args) {
...
do {
...
if (arraySize == -1) {
...
if (k != -1) {
...
}
}
} while (arraySze == -1 || k == -1);
...
}
Real code would be more complex and you would naturally(!) separate out the inputing, outputting and core "business" logic, which would make it easier to see what is going on.
bool exit = false;
while (!exit) {
...
...
if (k == -1) {
exit = true;
}
else {
List <Integer> ....;
quickselect(.......);
}
}
But as has been said before, your while loop is a valid usage in this situation. The other options would simply build upon the if statements to check for the boolean and exit.
While having a loop like this is not technically wrong, some people will argue that it is not as readable as the following:
bool complete = false;
while (!complete)
{
if (arraySize == -1)
{
complete = true;
break;
}
}
Additionally, it is sometimes a good idea to have a safety loop counter that checks to make sure the loop has not gone through, say, 100 million iterations, or some number much larger than you would expect for the loop body. This is a secure way of making sure bugs don't cause your program to 'hang'. Instead, you can give the user a friendly "We're sorry but you've discovered a bug.. program will now quit.." where you set 'complete' to true and you end the program or do additional error handling. I've seen this in production code, and may or may not be something you would use.
while ( true ) is perfectly fine here, since the condition is really "while the user doesn't want to quit"!
Alternatively you could prompt for both the inputs on one line to simplify the logic, and use "q" for quit: this allows you to refactor the loop to "while ( !line.equals("q") )".
The problem is that you're doing an awful lot in that loop, rather than separating the functionality into simple methods.
If you want to stick to a procedural approach, you could move the reading of the array size and k into separate methods, and use the fact that the result of an assignment is the assigned value:
for (int arraySize; ( arraySize = readArraySize ( input ) ) != -1;) {
final int k = readKthSmallestElement ( input );
List<Integer> randomData = generateRandomData(arraySize, 1, 100);
quickSelect(randomData, k);
}
However that's still a bit ugly, and not well encapsulated. So instead of having the two != -1 tests on separate variables, encapsulate arraySize, k and randomData in an object, and create a method which reads the data from the input, and returns either a QuickSelect object or null if the user quits:
for ( QuickSelect select; ( select = readQuickSelect ( input ) ) != null; ) {
select.generateRandomData();
select.quickSelect();
}
You might even want to go to the next stage of creating a sequence of QuickSelect objects from the input, each of which encapsulate the data for one iteration:
for ( QuickSelect select : new QuickSelectReader ( input ) ) {
select.generateRandomData();
select.quickSelect();
}
where QuickSelectReader implements Iterable and the iterator has the logic to create a QuickSelect object which encapsulates arraySize, k, the list and the quick select operation. But that ends up being quite a lot more code than the procedural variants.
I'd only do that if I wanted to reuse it somewhere else; it's not worth the effort just to make main() pretty.
Also note that "-1" doesn't match the regex "\\d+", so you really do have an infinite loop.
If you really don't like while(true) you can always go for for(;;). I prefer the latter because it seems less redundant.

Categories

Resources