Java Ternary Operator inside ternary operator, how evaluated? - java

Very basic question I suppose, I just wanted to know how this code is read:
return someboolean ? new someinstanceofsomething() : someotherboolean ? new otherinstance() : new third instance();
I guess now as I'm writing it I kind of understand the statement. It returns option one if true but then does another boolean check if false and returns one of the two remaining options? I'm going to continue to leave this question because I have not seen it before and maybe others have not as well.
Could you go on indefinitely with ternary inside of ternary operations?
Edit: Also why is this/is this not better for code than using a bunch of if statements?

It is defined in JLS #15.25:
The conditional operator is syntactically right-associative (it groups right-to-left). Thus, a?b:c?d:e?f:g means the same as a?b:(c?d:(e?f:g)).
In your case,
return someboolean ? new someinstanceofsomething() : someotherboolean ? new otherinstance() : new third instance();
is equivalent to:
return someboolean ? new someinstanceofsomething() : (someotherboolean ? new otherinstance() : new third instance());

Ternary operators are right-associative. See assylias's answer for the JLS reference.
Your example would translate to:
if (someboolean) {
return new someinstanceofsomething();
} else {
if (someotherboolean) {
return new otherinstance();
} else {
return new thirdinstance()
}
}
And yes, you can nest these indefinitely.

Related

java how to change this code from finding all true objects to find false

I have code that finds all the objects in the list that are true to getranonelectricity and prints them out. How do I change this code so it finds and prints out only false ranonelectricity objects?
Transport transports[]=new Transport[10];
transports[0]=Transport1;
transports[1]=Transport2;
transports[2]=Transport3;
transports[3]=Transport3;
transports[4]=Transport4;
transports[5]=Transport5;
transports[6]=Transport6;
transports[7]=Transport7;
transports[8]=Transport8;
transports[9]=Transport9;
for (Transport transportssssss : transports) {
if (transportssssss instanceof car) {
if (((car) transportssssss).getranonelectricity()) {
System.out.println(transportssssss);
Change
if(((car) transportssssss).getranonelectricity()){
to
if(!((car) transportssssss).getranonelectricity()){
The ! operator will invert the truth value of any Boolean expression.
Please read about Logical Operators in Java. For example this: https://www.dummies.com/programming/java/logical-operators-in-java/
You need a "Not" operator.

Java Lambda Expression for if condition - not expected here

Consider the case where an if condition needs to evaluate an array or a List. A simple example: check if all elements are true. But I'm looking for generic way to do it
Normally I'd do it like that:
boolean allTrue = true;
for (Boolean bool : bools){
if (!bool) {
allTrue = false;
break;
}
}
if (allTrue){
// do Something
}
But now I'd like to hide it into my if condition. I tried using Lambda Expressions for this, but it's not working:
if (() -> {
for (Boolean bool : bools)
if (!bool)
return false;
return true;
}){
// do something
}
If this were working I could do something more complicated like
if (() -> {
int number = 0;
for (MyObject myobject : myobjects)
if (myObject.getNumber() != 0)
numbers++;
if (numbers > 2)
return false;
return true;
}{
//do something
}
Is there a better way to do it is it just a syntax error?
UPDATE
I'm not talking about the boolean array, rather looking for a generic way to achieve that.
You can write, given for instance a List<Boolean>:
if (!list.stream().allMatch(x -> x)) {
// not every member is true
}
Or:
if (list.stream().anyMatch(x -> !x)) {
// at least one member is false
}
If you have an array of booleans, then use Arrays.stream() to obtain a stream out of it instead.
More generally, for a Stream providing elements of (generic) type X, you have to provide a Predicate<? super X> to .{all,any}Match() (either a "full" predicate, or a lambda, or a method reference -- many things go). The return value of these methods are self explanatory -- I think.
Now, to count elements which obey a certain predicate, you have .count(), which you can combine with .filter() -- which also takes (whatever is) a Predicate as an argument. For instance checking if you have more than 2 elements in a List<String> whose length is greater than 5 you'd do:
if (list.stream().filter(s -> s.length() > 5).count() > 2L) {
// Yup...
}
Your problem
Your current problem is that you use directly a lambda expression. Lambdas are instances of functional interfaces. Your lambda does not have the boolean type, that's why your if does not accept it.
This special case's solution
You can use a stream from your collections of booleans here.
if (bools.stream().allMatch((Boolean b)->b)) {
// do something
}
It is actually much more powerful than this, but this does the trick I believe.
General hint
Basically, since you want an if condition, you want a boolean result.
Since your result depends on a collection, you can use Java 8 streams on collections.
Java 8 streams allow you to do many operations on a collection, and finish with a terminal operation. You can do whatever complicated stuff you want with Stream's non-terminal operations. In the end you need one of 2 things:
use a terminal operation that returns a boolean (such as allMatch, anyMatch...), and you're done
use any terminal operation, but use it in a boolean expression, such as myStream.filter(...).limit(...).count() > 2
You should have a look at your possibilities in this Stream documentation or this one.

Error while using ternary operator

I'm writing my Code with Eclipse Juno and I'm using a hash table to set my dataImportObject depending on the entries in it.
Could anyone please tell me whats wrong about this:
ht is my hashTable with <String, Integer> pairs in it
(ht.containsKey("DEVICE_ADDRESS")) ?
dataImportObject.setDevice_Address(dataitems[ht.get("DEVICE_ADDRESS")]) :
dataImportObject.setDevice_Address("");
Could anyone please tell me whats wrong about this
Two things:
The conditional operator can't be used as a statement on its own, only as an expression
I assume these set methods have void return types, so they can't appear as operands in the conditional operator
Three options:
Use an if statement:
if (ht.containsKey("DEVICE_ADDRESS")) {
dataImportObject.setDevice_Address(dataitems[ht.get("DEVICE_ADDRESS")]));
} else {
dataImportObject.setDevice_Address("");
}
Use the conditional operator inside the setDevice_Address call, or even clearer, beforehand:
String address = ht.containsKey("DEVICE_ADDRESS")
? dataitems[ht.get("DEVICE_ADDRESS")] : "";
dataImportObject.setDevice_Address(address);
If you know that your hashtable won't have any null values, you can avoid the double lookup:
Integer index = ht.get("DEVICE_ADDRESS");
String address = index == null ? "" : dataitems[index];
dataImportObject.setDevice_Address(address);
You can't set the return type of ternary condition to void.
Use if else for that.
Possible duplicate

why unexpected behaviour for conditional operator

I have a piece of code like follows
public class Test{
public static void main(String[] args) {
System.out.println(true?false:true == true?false:true);
-----------------------
}
}
The output is false. If you are using Eclipse you get a wavy (dashed here) line and warning like "Comparing identical expressions". Note the start of the wavy line.
I changed the code to the following
public class Test{
public static void main(String[] args) {
System.out.println((true?false:true) == (true?false:true));
---------------------------------------
}
}
The output is true. If you are using Eclipse you get a wavy (dashed here) line and warning like "Comparing identical expressions". Note the start of the wavy line now.
Why the difference?
Because ternary operator (?:) has lower priority than equality operator (==). This means that:
true?false:true == true?false:true
is actually interpreted as:
true?false:(true == true?false:true)
This, in turns, is evaluated to:
true?false:((true == true)?false:true)
cont.:
true?false:(true?false:true)
...and eventually:
true?false:(false)
and eventually:
true?false:false
And obviously this explains the output of the first code snippet. Eclipse correctly recognizes operator precedence and highlights possibly incorrect statement.
UPDATE: Thanks for all the comments. In fact I forgot about operator precedence on the left side. I checked the exact behaviour using the program below:
public static boolean a(char label, boolean result) {
System.out.println(label);
return result;
}
public static void main(String[] args) {
System.out.println(
a('a', true) ? a('b', false) : a('c', true) == a('d', true) ? a('e', false) : a('f', true)
);
}
The results are consistent with #Milad Naseri suggestion.
There is nothing unexpected here, the answer is operator precedence.
In the first case it is:
true?false:(true == true?false:true)
While the in the second case your paretheses override the precedence rules.
In case your problem is the difference of outcomes, this is because of the order of precedence of the operators you use. Check here for details. According to that order of precedence:
true ? false : true == true ? false : true
is the same as this:
true ? false : ((true == true) ? false : true)
so it will always evaluate to false. You could put anything after the colon since it's never evaluated anyway (if I remember correctly and the ternary operator uses lazy evaluation); the reason for this is that
true ? A : B
always evaluates to A.
On the other hand,
(true ? false : true) == (true ? false : true)
will have both sides of the comparison operator == evaluate to false, so
false == false
which is a true statement.
So the difference here is the order in which the operators are evaluated, which is determined by the parentheses you use and, if there is ambiguity that isn't resolved by parentheses, by the order of precedence of the operators that are used.
In general, the ternary operator "? :" works like this
A ? B : C
If A is true, evaluate to B, else evaluate to C. A has to be a boolean expression, B and C can be whatever you want; you'll have to deal with type mismatches though if you want to assign the evaluated value to a variable and they are of different types.
That is because the conditional equality operator (==) takes precedence over the ternary conditional ?:. So, in a?b:x==y?z:t x==y?z:t is evaluated before a?b:x and y?z:t are.

Boolean != false

In Java, you would usually say that
if(someBool != false)
is the same as
if(someBool)
But what if someBool is not of type boolean but Boolean, and its value is null?
If you want to handle Boolean instances as well as primitives and be null-safe, you can use this:
if(Boolean.TRUE.equals(someBool))
It will throw a NullPointerException (autounboxing of null throws NPE).
But that only means that you must not allow a null value. Either use a default, or don't use autounboxing and make a non-null check. Because using a null value of a boolean means you have 3, not 2 values. (Better ways of handling it were proposed by Michael and Tobiask)
Use ApacheCommons BooleanUtils.isTrue() or .isFalse()
If someBool is Boolean
if (someBull != null && someBull) {
//Yeah, true.
}
Since Boolean can be null make sure you avoid NullPointerException by checking for not null.
I did a little test:
Boolean o = null;
try {
System.out.println(o ? "yes" : "no");
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println((o != false) ? "yes" : "no");
} catch (Exception e) {
e.printStackTrace();
}
The output is surprising:
java.lang.NullPointerException
at btest.main(btest.java:10)
java.lang.NullPointerException
at btest.main(btest.java:15)
The first NPE is to be expected, because o will be autounboxed (and that fails because it's null). The second happens for the same reason, but it doesn't feel natural. Anyway, the solution is to do:
System.out.println(!Boolean.FALSE.equals(o) ? "yes" : "no");
You can however compare a null Boolean with a Boolean instance. For example :
Boolean myBool = null;
System.out.println(myBool == Boolean.FALSE);
System.out.println(myBool == Boolean.TRUE);
prints :
false
false
Good illustrations of the difference between the primitive boolean & the object Boolean. The former can be only true or false. The latter can be true, false, or unknown/undefined. (i.e., null). Which you use depends on whether you want to deal with two use cases or three.
It's old, but Boolean.valueOf(null) is false, just like Boolean.valueOf(false) is false.
Actually the Boolean constructor accepts null, returns FALSE and doesn't throw a NullPointerTantrum.
new Boolean(null);
<false>
This has the added bonus of also giving a thruthy response to the string "true" which is not the case for Boolean.TRUE.equals but we are more restricted again having only constructors for Strings and Booleans.
Something you can overcome with string concatenation, which is also null-proof.
new Boolean(""+null);
<false>
new Boolean(""+false);
<false>
new Boolean(""+new Object());
<false>
new Boolean(""+6);
<false>
new Boolean(""+new Integer(9));
<false>
Ensuring that all the TRUE options, available in java, still remains.
new Boolean(""+true);
<true>
new Boolean(""+"true");
<true>
If it's Java 7+ you can use
import java.util.Objects;
And
if (Objects.equals(someBool, true))
As Boolean will give you an object, you must always check for NULL before working on the object
If its null then you'll get a NullPointerException

Categories