Java & and && operators troubles - java

I'm trying to figure out why & operator throws an exception and suspends my program but when I use && operator the program works with no errors.
Here is the portion of the code:
books is an arraylist of objects Book.
areYouBook returns true if the book's ISBN I'm looking for matches a.
The method findBook checks if I already have the book in the arraylist. When the method returns null, it means I have to create the book and add it to the ArrayList.
Thank you very much for your help!
public Book findBook(int a){
int i=0;
while((i<(books.size()))&!((books.get(i)).areYouBook(a)))
i++;
if(i<(books.size()))
return books.get(i);
else
return null;
}

I can tell you from here that the difference between the & operator and the && operator is that && will check the first expresion, and if it evaluates to false, then it will simply break from the check, but the & operator will run the following expression regardless of whether or not the first one turned out to be false.
So, the code you have written will check (i<(books.size())), and whether or not that turns out to be false, !((books.get(i)).areYouBook(a)) will still be executed.
If however, you used && and (i<(books.size())) was false, the second part of your check, which is !((books.get(i)).areYouBook(a)), will not be executed.
I hope this helps.
Edit:
You mentioned an error being thrown when you used the & operator instead of the && operator. Since the & operator does run the second expression even if the first one is false, I'm wondering if your second expression is actually throwing an error, and is getting called when you use &.
Edit 2:
Ok. Lets say that books has a size of 12 (indexes 0-11) just for demonstration. So, when you use the & operator, your while loop runs until i is 12. When i is 12, the loop executes (i<(books.size())) (which returns false) and CONTINUES to execute !((books.get(i)).areYouBook(a)). Inside the second expression, books.get(i) is being called, when i is 12. The books list only goes from indexes 0-11, throwing a java.lang.IndexOutOfBoundsException.

java conditional operators says:
the operators && and || exhibit "short-circuiting" behavior, which means that the second operand is evaluated only if needed.
the logical AND operator && will be short-cuircuting if the left side condition is false, on the other hand, when the left side condition is false the right side condition is never be executed.
but the bitwise & operator performs a bitwise AND operation.

The logical AND that you're trying to use is represented by the && symbol i.e. True && False resolves to False. The single ampersand "&" represents a bitwise AND i.e. 0101 & 0100 resolves to 0110.

Related

Is there a difference in ordering of conditions between the && operator?

I'm a fairly new beginner to java and was practicing some leetcode here: https://leetcode.com/problems/same-tree/
My solution to the question was:
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null){
return true;
}
return (p.val == q.val)&&(p != null && q != null)&&
isSameTree(p.left, q.left)&&
isSameTree(p.right, q.right);
}
}
and I just couldn't get it to work with it resulting in a nullpointer error. But then a mere switch of the conditional:
return (p != null && q != null)&&(p.val == q.val)&&
isSameTree(p.left, q.left)&&
isSameTree(p.right, q.right);
and all of a sudden it works. No idea why. I thought && was a logical and operator, and so A and B is the same as B and A ... what's going on?
In most programming languages, the expressions are evaluated from left to right. In your earlier approach, p.val may result in NullPointerException when p is null. To avoid this, you should always check the null conditions before in your AND/OR expressions. Which is exactly what you did (without realizing I guess.).
In math or boolean algebra or whatever, the AND operator has the associative and the commutative properties, so math-wise, no.
However, most all programming languages use lazy evaluation for their Boolean and operators. If the first operand is false and the operator is &&, then why bother evaluating the second operand if you know it is just going to return false?
Using that, you can avoid errors (like the one you posted) by changing the order of the operands.
Like, if you wanted to avoid a object is undefined error when trying to access an object's members, you can do if(object != undefined && object.isExample). If object is undefined, then it it knows that that expression is false and quits there.
The && operator is stand for 'and' in logic, which returns true only if both of conditions are true.
So, the left condition checked first, and if it is false, the right condition isn't checked.
Because of that, I suggest you to put the conditions by this order (the higher in this order should be the left condition):
Must checked before working conditions (for example not null conditions).
Low time complexity conditions (for example checking the value of variable).
High time complexity conditions (for example searching in/sorting an array).
In order && operator to retrieve true all conditions need to return true so we first check the left conditions and only if its true we check the all the rest one by one,
If any condition fails we stop checking all others.
So in your case you need to get all the low complexity operation first
More reading about short circuit evaluation
https://en.m.wikipedia.org/wiki/Short-circuit_evaluation

java how to determine logical expression minimum values to evauate

I have an expression (an example)
(value1<15 AND value2>25) OR ((value3>0 and vaue4<5) OR (value5<6 and value7>8))
The issue is value1-7 are calls to external services, which are expensive. And we need to reduce cost, so we need to make a minimum number of calls to evaluate this expression. For example if we have
(value1<15 AND value2>25)
evaluated to true, we don't need to evaluate right part, so we don't need to make useless calls to external services. How to determine in java (or may be just in math) when we need to stop, and further evaluations will not make any effect?
UPDATE
I have 5 workers that works on 5 different servers.
first worker:
accept(expression)
value1=calculateValue1()
setValueToExpression(expression, 0, value1)
enough=expression.checkIsItEnough()
if(!enough){
determineNextWorker(expression)
sendToNExtWorker()
}
else return expression.evaluate()
The second worker
accept(expression)
value2=calculateValue2()
setValueToExpression(expression, 1, value2)
enough=expression.checkIsItEnough()
if(!enough){
determineNextWorker(expression)
sendToNextWorker()
}
else return expression.evaluate()
.....................
As I said in comments, I clearly understand that if we can write
evaluator.evaluate("(value1<5 and value2>6) or (value3>5 and value4>7)")
it evaluates it as all of us know, but I don't have this ability due to many reasons. I also can't make it function calls value1()<15...
It's happening synchronously, one by one but even on different servers, kinda offline evaluation. Hope it's clear
Consider normal short-circuit intermediate code for:
(value1<15 AND value2>25) OR ((value3>0 and value4<5) OR (value5<6 and value7>8))
if value1<15 goto value2_test else goto value3_test
value2_test:
if value2>25 goto success else goto value3_test
value3_test:
if value3>0 goto value4_test else goto value5_test
value4_test:
if value4<5 goto success else goto value5_test
value5_test:
if value5<6 goto value7_test else goto fail
value7_test:
if value7>8 goto success else goto fail
You could simplify things substantially by having a tree representation of your expression, and passing around subexpressions represented by trees rather than the whole expression.
For example, the first worker would have two subexpressions: value2>25 and (value3>0 and value4<5) OR (value5<6 and value7>8). Select the first one if the test succeeds, the second one if it fails.
The value2>25 worker would have two subexpressions: "success" and (value3>0 and value4<5) OR (value5<6 and value7>8)
I am not aware of any library to do the conversions. If it exists, it would be in the domain of compiler construction.
I would try very hard to change this to something where one worker could organize the job, and simply call on other workers to evaluate one relational condition.
========================================================================
More detail, because this seems to be the sort of answer the OP is looking for:
Terminology:
"term" -> A comparison or Boolean variable, such as value2>25
"product" -> The AND of some Boolean expressions
"sum" -> The OR of
some Boolean expressions.
Consider only sum-of-products expressions, such as (value1<15 AND value2>25) OR ((value3>0 and value4<5) OR (value5<6 and value7>8)). This is not a very significant limitation. Many optimizations and simplifications used in digital logic design depend on converting arbitrary logical expressions to sum-of-products.
At each step, the worker for the leading term of an expression is called. Depending on the expression and the outcome of its test, it can declare success, declare failure, or calculate a new expression that must be passed to the worker for its leading term.
if this worker's condition is true
if more terms in current product
remove the leading term from the current product
pass the new expression to the worker for the next term
else
declare success
else
if there is another product
remove the leading product from the expression
pass the new expression to the worker for the new leading product's leading term
else
declare failure
A standard condition will work that way (short circuit) because it will only evaluate the expressions if necessary (if the first part of an || condition is true it won't evaluate the rest):
if ((value1() < 15 && value2() > 25) || (value3() > 0 && vaue4() < 5) ...)
Note that I have replace the values by method calls - if you precalculate each value of course it won't work...
Examples:
if your condition value1() < 15 returns false, then value2() won't be called
if the first condition value1() < 15 && value2() > 25 is true, value3() and value4() won't be evaluated.
References:
See JLS #15.23 (emphasis mine):
The conditional-and operator && is like &, but evaluates its right-hand operand only if the value of its left-hand operand is true.
Similarly in JLS #15.24:
The conditional-or operator || operator is like |, but evaluates its right-hand operand only if the value of its left-hand operand is false.
Conditional logic by default evaluates the least amount of conditions needed to obtain an evaluation result. This is not specific to Java. This is how things work. Also, the grouping parentheses are completely optional in your case.
Depending on your use case, you may want to push forward inside the condition the expressions that are most likely to be true. And perhaps consider caching for a certain amount of time some of the results, if applicable.

JAVA looping logic error with NOT .equalsIgnoreCase()

I'm trying to use equalsIgnoreCase() in a while loop to try and check if something other than what was intended to be written was written by using the NOT (!) operator. For example:
String temp="A";
boolean x =(!temp.equalsIgnoreCase("a")) ;
See, this works with a while loop. If it's not A, it will keep looping but this next line does not
boolean x =(!temp.equalsIgnoreCase("a") || !temp.equalsIgnoreCase("b")) ;
This does not seem to work anymore. This returns true, no matter what you type, even if it is a or b. So when I use the whole line of code to check for any of the letters that are not suppose to be used:
while (!temp.equalsIgnoreCase("A") || !(temp.equalsIgnoreCase("B")) ||!temp.equalsIgnoreCase("D")|| !temp.equalsIgnoreCase("P") || !temp.equalsIgnoreCase("S"))
{ ***Do Code***}
it loops whatever you put in, even if it will equal one of the letters.
When there is more than one !temp.equalsIngnoreCase, the code does't work with OR (||).
The only way I can get it to work is if I change the OR to AND
while (!temp.equalsIgnoreCase("A") && !(temp.equalsIgnoreCase("B")) && !temp.equalsIgnoreCase("D")&& !temp.equalsIgnoreCase("P") && !temp.equalsIgnoreCase("S"))
Even though I seem to have found a solution, I still don't understand why OR doesn't work but AND does. I removed the NOT to see if everything works, and it seems to loop perfectly when one of the letters is entered.
it loops whatever you put in, even if it will equal one of the letters.
Yes, of course it does.
You're asking it to keep going while it isn't A or it isn't B. Well nothing can be both A and B... if the value is equal to B then it won't be equal to A so the first operand will keep the loop going. If the value is equal to A then it won't be equal to B so the second operand will keep the loop going.
Your solution of changing to AND is correct - you want the value to not be A and not be B (i.e. it's neither A nor B).
Alternatively, you could use OR internally, but put a NOT around the whole thing:
while (! (temp.equalsIgnoredCase("A") || temp.equalsIgnoreCase("B") || ...))
I still don't understand why OR doesn't work but AND does
The expression using || will always be true at any given value of temp. Because, temp cannot be both a and b at the same time. If it is a, then the 2nd part of || will be true, and if it is equal to b or any other value, the first part will be true, thus making the entire expression true in both the cases.
With &&, your while will only be true, if temp is neither of a nor b.
Alternatively, if you are going to test temp against many values, you can change your while condition to look simpler:
while (!"ABDPS".contains(temp.toUpperCase())) {
}
its a foul logic. the code
(!temp.equalsIgnoreCase("A") || !(temp.equalsIgnoreCase("B")) ||!temp.equalsIgnoreCase("D")|| !temp.equalsIgnoreCase("P") || !temp.equalsIgnoreCase("S"))
means
if char is not A, or not B, or not D, or not P, or not S. It will always evaluate to true, since is char is A, it will neither be B,D,S nor P. so is for the others.
if you want it to be OR logic, it should be:
(!(temp.equalsIgnoreCase("A") || (temp.equalsIgnoreCase("B")) ||temp.equalsIgnoreCase("D")|| temp.equalsIgnoreCase("P") || temp.equalsIgnoreCase("S")))
which means, not when the char is either of A, B, D,S or P
This is all about logic.
A OR B means that is is true when A is true or B is true or both are true.
In your special case it is only possible that one of your equalsIgnorecase() can ever work, so you wrote something like a tautology which means an endless loop.
You can read about boole algebra here: http://en.wikipedia.org/wiki/Boolean_algebra_%28structure%29
Kind of some theory but it explains what you need to know when you write boolean expressions.
Hope this helps :)

Does Java check all arguments in "&&" (and) operator even if one of them is false?

I have such code:
if(object != null && object.field != null){
object.field = "foo";
}
Assume that object is null.
Does this code result in nullPointerException or just if statement won't be executed?
If it does, how to refactor this code to be more elegant (if it is possible of course)?
&& does short circuit while & would not.
But with simple questions like this, it is best to just try it (ideone can help when you don't have access to a machine).
&& - http://ideone.com/LvV6w
& - http://ideone.com/X5PdU
Finally the place to check for sure would be the JLS §15.23. Not the most easy thing to read, the relevent section states:
The && operator is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.
Java does have short circuit evaluation, i.e. your code should be ok
One way to know it! Test it! How? Well, make a method which prints out something:
public static boolean test(int i)
{
System.out.println(i);
return false;
}
...
if (test(1) && test(2) && test(3))
{
// not reached
}
This prints:
1
So the answer on your question is "no".
Best way to find out would be try it, especially for a single line question. Would have been faster, too.
The answer is that Java will not execute the body of the "if".
This will not throw any NullPointerException . The condition will be evaluated from left to right and the moment first false expression is found it will not evaluate remaining expression.
Maybe this other question helps you:
Differences in boolean operators: & vs && and | vs ||
Java has short circuit evaluation, so it will be fine.
The code looks ok to me, but do you actually need to check object.field != null? I think that test can be omitted as you never use the variable, just set it.
On a side-note, most programmers wouldn't access fields directly (object.field) but rather through getters/setters (object.setField(x);). Without any more context to go on, I can't say if this is appropriate in your case.
&& and || conditions stops at the point they can decide whether the condition is true/false, in your case, the condition will stop right after object != null and I think that your code is just fine for this case
If you want all of your boolean expressions evaluated regardless of the truth value of each, then you can use & and | instead of && and ||. However make sure you use these only on boolean expressions. Unlike && and ||, & and | also have a meaning for numeric types which is completely different from their meaning for booleans.
http://ibiblio.org/java/course/week2/46.html
Although short circuiting would work here, its not a guarantee that (like I have done many times) you'll get the order wrong when writing another, it would be better practice to nest those if statements and define the order you want the boolean checks to break:
if(object != null)
{
if(object.field != null)
{
object.field = "foo";
}
}
This does exactly the same as you're essentially saying, if the first boolean check fails don't do the second; it is also nullPointerException safe as object.field will not be checked unless object is not null
Using short-circuiting on booleans can become annoying later on as when you have a multiple bool if statement it becomes trickier to efficiently debug which part short circuited.

bad java compiler optimization?

I have this piece of code:
private void prepareContent() {
log.info("do something");
// success?
boolean suc = false;
suc = suc || uncompressToContent("file.tar.gz");
suc = suc || uncompressToContent("file.tgz");
for (int i = 0; i <= 9; i++) {
suc = suc || uncompressToContent("dir/" + i + ".tgz");
suc = suc || uncompressToContent("dir/" + i + ".tar.gz");
}
if (!suc) {
log.error("unable to do something");
}
}
The function returns false for "file.tar.gz" and file.tgz".
The problem is the the call to uncompressToContent("dir/1.tgz") returns true and the code stops its execution. The remaining code is not executed.
I'm not sure if this is an error in the compiler. What do you think?
Added: I forgot to mention that I need to execute all the calls to uncompressToContent and check if any returns true, using the fewer instructions as possible.
There is no error in the compiler.
As soon as suc is set to true (i.e. from the first uncompressToContent call) then all of the future expressions will return true without calling uncompressToContent. This is becuase you are using short circuit boolean or ("||") which do not evaluate the second argument if the first argument is true.
If you want all the calls to be made, use the normal or operator ("|") instead.
If the uncompress method returns true if there was a successful decompression, then suc would become true the first time that this happens. Once suc is true, all the other conditions would be true as soon as suc is evaluated, so the other part of the OR would not be evaluated. Thus, no decompressions will be attempted once at least one is successful.
This is called short circuiting and is the correct behavior and is a very useful property in most languages. And is also not a compiler optimization since it is part of the defined behavior of the language.
Beyond this answer, there are, I think, ways to make this code more readable.
First, are you sure that you want to OR rather than AND here? It seems like you want to quit as soon as one file did not compress decorrectly, not stop as one did decompress correctly.
Second, a better design, IMHO, would be to create a list of all the filenames you want to decompress, and then do a for-each over that list and do all the decompressions, it would make things more readable.
Third, if in most cases decompression would be successful, I think that exception handling is much better than boolean return values.
Here is how I would write something like this (and I would break it into functions)
List<String> filenames = new ArrayList<String>();
this.collectFilenamesToDecompress(filenames) // Write one or more than one functions of this sort based on the semantics of your problem
try
{
for(String filename: filenames)
{
uncompressFile(filename); // This will throw an exception if there is a failure
}
} catch(Exception e)
{
// Announce that there was an error and you stopped decompressing because there was an error.
// Return or quit
}
// If you got here, everything is great!
This behavior is by design.
Logical operators in most languages are short-circuiting.
In the expression a || b, b will only be evaluated if a is false.
Therefore, once suc becomes true, none of the other calls to uncompressToContent will be evaluated.
I think the compiler is doing something like: suc = uncompressToContent("file.tar.gz") || uncompressToContent("file.tgz") || uncompressToContent("...") || ... So, when it finds one true value, the execution is stopped. Is this feature documented?
Yes. It is clearly documented in the Java Language Specification section 15.24, where it says this:
"The || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false."
The JLS then goes on to explain exactly what happens in excruciating detail. Follow the link above if you are interested.
Oh yea, and in this respect the Java || operator behaves the same as in C, C++, C#, Perl and many other programming languages.

Categories