java Nested If or single if - java

I have a basic doubt regarding the execution of the following code block (Sample):
String version = computer.getSoundcard().getUSB().getVersion();
Which might throw NullPointerException if Soundcard isn't there.
So I have ,
Option 1 :
if(computer!=null &&
computer.getSoundCard() !=null &&
computer.getSoundCard().getUSB()!=null) {
version = computer.getSoundcard().getUSB().getVersion();
}
Option 2 :
if(computer !=null){
SoundCard sc = computer.getSoundCard();
if(sc!=null){
USB usb = sc.getUSB();
if(usb!=null){
version = usb.getVersion();
}
}
}
As per my understanding the Option 1 will have extra overhead as it has to evaluate the same expression multiple times like computer.getSoundCard() 3 times, computer.getSoundCard().getUSB() 2 times.
Is my understanding correct ?
EDIT 1: Changed Option 2 from
version = computer.getSoundcard().getUSB().getVersion();

A better approach is to extract this USB-version-getting code into another single method, say getComputerUsbVersion(), then flatten the super long if or the nested if-else block into several simple if blocks:
public String getComputerUsbVersion(Computer computer) {
if (computer == null) return null;
SoundCard soundCard = computer.getSoundCard();
if (soundCard == null) return null;
USB usb = soundCard.getUSB()
if (usb == null) return null;
return usb.getVersion();
}
As you can see, the code is much cleaner and easy to understand, the super long if condition or the nested if-else block is also avoided. You can even add more condition checking code to this method later on very easily.

As per my understanding the Option 1 will have extra overhead as it has to evaluate the same expression multiple times
Yes, these calls would be made multiple times. However, you can shorten it if you make assignments as part of your conditional, like this:
SoundCard sc;
USB usb;
if(computer != null && (sc = computer.getSoundCard()) != null && (usb = sc.getUSB()) != null) {
version = usb.getVersion();
}
Note that references to sc and usb inside the expression and inside the conditional are safe, because && evaluation is guaranteed to stop upon reaching the first false in the chain.

Related

Leaving the code in an else if() blank in order to escape the if statement

I'm sorry for the strange title, I couldn't find the exact wording that I wanted but I'll do my best to explain my question here. Basically I have some code that goes like this
if(both inputs are not null)
{
Do this
}
else if(both inputs are null)
{
}
else if(one input is null and the other isn't)
{
throw new Exception("Both inputs must have a value or neither should");
}
if I don't use the middle else if the last else if, the program will throw the exception no matter whether one or both inputs are null. I'm wanting it so that the program sees that both inputs are null and does nothing while continuing with it's execution. I'm using this data to pass to a SQl query and if one of the inputs are null it acts up. I might just be messing up the logic but I was wondering if this is considered bad practice. I can't think of a problem because there isn't a way that this could execute code accidentally. If there is a better way or if this is considered bad practice I would like to hear other ways to go about this. Thanks.
EDIT: clarified question
I think I'm missing something here. Your description doesn't seem to match your code.
In the pseudo-code you wrote, if both inputs are null, no exception should be sent, and that's what you want. But you are saying the exception is still sent ? Something is up here. Can you post something closer to your actual code ?
What you describe seems closer to the behavior of a switch case, where an empty "case" would just drop to the next one.
Both diregarding that, you can avoid those empty "else if" by re-ordering your tests :
if(both inputs are not null)
{
Do this
}
else if(one input is null and the other isn't)
{
throw new Exception("Both inputs must have a value or neither should");
}
This way, no need for an additional empty else if.
You can simplify the code if the language you are using has an Exclusive OR operator. For example in C#:
string A = null;
string B = "Hello World";
if ( A != null && B != null)
{
// Do this
}
else if ( A == null ^ B == null )
{
throw new Exception("Both inputs must have a value or neither should");
}
The result of x ^ y is true if x evaluates to true and y evaluates to false, or x evaluates to false and y evaluates to true.
The easiest fix, in my opinion, would be to change your code to below
if(both inputs are not null)
{
Do this
}
else if((input1==null && input2!=null) || (input1!=null && input2==null))
{
throw new Exception("Both inputs must have a value or neither should");
}
Refactor out this logic in its own method, and then write it as following:
private void refactoredMethod(Input i1, Input i2) {
//Do nothing if both inputs are null.
if (i1 == null && i2 == null)
return;
//Throw if either of them is null.
if (input1 == null || input2 == null)
throw ...
//Neither input is null, do the normal processing.
//so, "Do this"
}
Why are you not checking if either one of the inputs is null?
Then you could throw an exception and continue afterwards if no exception was thrown.
So something like this (in java terms):
if(firstInput == null || secondInput == null) {
throw new IllegalArgumentException("Input must not be null");
}
// do what you want afterwards
How about this:
bool A = (input1 == null), B = (input2 == null);
if (A != B) {
throw new Exception("Both inputs must have a value or neither should");
}
I understand that source code is sometimes better readable with empty blocks for certain conditions. I assume this is what you want to do. Example:
if(street!=null && zip!=null)
{
storeAddress(street,zip);
}
else if(street==null && zip==null)
{
; // Do nothing
}
else // only one of street or zip was provided
{
throw new Exception("Street and zip code must be filled together or both left empty");
}
I use the semicolon here to avoid warnings from SpotBugs. This way I tell Spotbugs (and other developers), that the block is empty on purpose.
The last condition of your example is redundant, so I turned it into a comment.

ArrayList to Stream in Java by grouping

I would like to get the highest score group by Id .If two highest score's are same then i would like get the highest score based on lowest Optional ID.I would like to get it in Java Stream.So far this code works.Is there any efficient way to rewrite this code in java stream
Example :
records=record.Person(batchNumber);
List<Person> highestRecords = new ArrayList<>();for(
Person s:records)
{
if(!highestRecords.isEmpty()) {
boolean contains = false;
for(Person ns: new ArrayList<>(highestRecords)) {
if(s.Id().compareTo(ns.Id()) == 0) {
contains = true;
if(s.getScore.compareTo(ns.getScore()) > 0
&& s.optionalId().compareTo(ns.optionalId()) < 0) {
highestRecords.remove(ns);
highestRecords.add(s)
}
}
}
if(contains == false) {
highestRecords.add(s);
}
}else {
highestRecords.add(s);
}
}
}
Don't convert this to a stream.
There is no one pure operation happening here. There are several.
Of note is the initial operation:
if(getNewPendingMatches.size() > 0)
That's always going to be false on the first iteration and you're always going to add one element in.
On subsequent iterations, life gets weird because now you're trying to remove elements while iterating over them. A stream cannot delete values from itself while iterating over itself; it only ever processes in one direction.
As written this code should not be converted to a stream. You won't gain any benefits in doing so, and you're going to actively harm readability if you do.

How to skip evaluating remaining part of arithmetic expression after 0 * ... in Java

In logic expressions remaining part would be skipped if it is unnecessary
boolean b = false && checkSomething( something)
//checkSomething() doesn't get called
What is a good way to achieve the same with arithmetic expressions ?
int i = 0 * calculateSomethig ( something )
It is possible to add ifs before * . But is there a more elegant way to solve this problem? Without of adding much stuff into expression, so that expression itself would look as close to original as possible
Why i do not want to use ifs?
from
return calculateA() * calculateB()
it'll become bulky and unclear
int result
int a = calculateA();
if (a!=0) {
result = a*calculateB()
}else{
result = 0
}
return result
8 lines of code instead of 1,
those expressions might be more complex than a*b
those expressions represent business logic so i want to keep them
clear and easily readable
there might be whole bunch of them
Why do i bother with this at all?
Because calculation methods might be expensive
uses values form other places, where searches and sorts are happening
lots of those expressions can be executed at once ( after user event and user should see result "instantly"
P( *0 in expression ) >0.5
&& and || are called short-circuit operators because they don't evaluate if the JVM will find the value of the whole expression without evaluating the whole expression. For example, the JVM does not have to evaluate the second part of the following expression to tell it evaluates to true:
6 == (2 + 4) || 8 == 9
The JVM does not have to evaluate all of the following expression either to tell it evaluates to false:
9 == 8 && 7 == 7
The multiplication operator (*) is not a short-circuit operator. And so, it does not behave that way. You can do this as you mentioned using if statements. There is no predefined way to do this.
You can create a structure that uses lambdas to evaluate its arguments lazily:
class LazyMul implements IntSupplier {
private final IntSupplier [] args;
private LazyMul(IntSupplier[] args) {
//argument checking omitted for brevity :)
this.args = args;
}
public static LazyMul of(IntSupplier ... args) {
return new LazyMul(args);
}
#Override
public int getAsInt() {
int res = 1;
for (IntSupplier arg: args) {
res *= arg.getAsInt();
if (res == 0)
break;
}
return res;
}
}
Of course this is even longer but using it is as simple as LazyMul.of(this::calculateA, this::calculateB), so if you use it several times, it's better than having an if every time around.
Unfortunately with complicated (particularly nested) expressions readability suffers, but these are the limitations of Java as a language.

Will there be any performance difference in following code?

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

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