How to combine equality operators in an if statement in java? - java

In python, you can do
if(a!=b!=c)
How can you do the same thing in Java without having to separate them and write all the "&&" operators? I'm trying to check that all 10 elements are not equal, and I don't want to have to write the equality statement 45 times.

You cannot do that operation in Java. Note furthermore that if a, b, etc., are not primitives, then you should probably be using equals instead of == (or !=). The latter only check for object identity, not equality of values.
If you want to check whether 10 elements are all distinct, you can throw them into a Set implementation (such as HashSet) and check that the set contains 10 elements. Or better (thanks to #allonhadaya for the comment), check that each element was added. Here's a generic method that works for an arbitrary number of objects of arbitrary type:
public static <T> boolean areDistinct(T... elements) {
Set<T> set = new HashSet<T>();
for (T element : elements) {
if (!set.add(element)) {
return false;
}
}
return true;
}
If your elements are primitives (e.g., int), then you can write a non-generic version for the specific type.

Something wrong in your program, if you need to compare 45 variables.
Try to use arrays and cycles.

There's no such option in java (you cannot do such thing without using &&). Java is not Python

Honestly, no, there's no native way to do this in Java.
But, why don't we implement the syntactic sugar for Python's all method instead? With varargs, it's not difficult. It does have an O(n) runtime cost, though.
public static boolean all(Boolean... theBools) {
Boolean result = Boolean.TRUE;
for(Boolean b : theBools) {
if(null == b || !b) {
result = Boolean.FALSE;
break;
}
}
return result;
}
You can use it then like this:
if(YourClass.all(a, b, c, d, e, f, g, h, i, j)) {
// something to do if ALL of them are true
}

I agree that Set is probably the most efficient solution, but if you need to supply some kind of customization to the comparison, you could use something like...
Comparable[] values = new Comparable[]{1, 2, 3, 4, 5};
boolean matches = true;
for (int outter = 0; outter < values.length; outter++) {
for (int inner = outter + 1; inner < values.length; inner++) {
matches &= values[outter].compareTo(values[inner]) == 0;
}
}
System.out.println(matches);

Related

Add additional rules to the compare method of a Comparator

I currently have a code snippet which returns strings of a list in ascending order:
Collections.sort(myList, new Comparator<MyClass>() {
#Override
public int compare(MyClass o1, MyClass o2) {
return o1.aString.compareTo(o2.aString);
}
});
While it works, I would like to add some custom "rules" to the order to put certain strings to the front. For instance:
if(aString.equals("Hi")){
// put string first in the order
}
if(aString begins with a null character, e.g. " ") {
// put string after Hi, but before the other strings
}
// So the order could be: Hi, _string, a_string, b_string, c_string
Is it possible to customize the sorting of a list with a Comparator like this?
The answer from MC Emperor is quite nice (+1) in that it fulfills the OP's requirement of not using Java 8 APIs. It also uses a neat internal function technique (the getOrder method) of mapping conditions to small integer values in order to effect a first-level comparison.
Here's an alternative that uses Java 8 constructs. It assumes that MyClass has a getString method that does the obvious thing.
Collections.sort(myList,
Comparator.comparing((MyClass mc) -> ! mc.getString().equals("Hi"))
.thenComparing(mc -> ! mc.getString().startsWith(" "))
.thenComparing(MyClass::getString));
This is pretty opaque until you get used to this style. The key insight is that the "extractor" function that's supplied to Comparator.comparing and Comparator.thenComparing often simply extracts a field, but it can be a general mapping to any other value. If that value is Comparable then an additional Comparator for it needn't be provided. In this case the extractor function is a boolean expression. This gets boxed to a Boolean which as it turns out is Comparable. Since false orders before true we need to negate the boolean expression.
Also note that I had to provide an explicit type declaration for the lambda parameter, as type inference often doesn't work for chained comparator cases such as this one.
That's possible.
Using Java 8 features
You could pass a function to the Comparator.comparing method to define your rules. Note that we simply return integers, the lowest integer for the elements which should come first.
Comparator<MyClass> myRules = Comparator.comparing(t -> {
if (t.aString.equals("Hi")) {
return 0;
}
else if (t.aString.startsWith(" ")) {
return 1;
}
else {
return 2;
}
});
If you want the remaining elements to be sorted alphabetically, you could use thenComparing(Comparator.naturalOrder()), if your class implements Comparable. Otherwise, you should extract the sort key first:
Collections.sort(myList, myRules.thenComparing(Comparator.comparing(t -> t.aString)));
Note that the actual specific numbers returned don't matter, what matters is that lower numbers come before higher numbers when sorting, so if one would always put the string "Hi" first, then the corresponding number should be the lowest returned (in my case 0).
Using Java <= 7 features (Android API level 21 compatible)
If Java 8 features are not available to you, then you could implement it like this:
Comparator<MyClass> myRules = new Comparator<MyClass>() {
#Override
public int compare(MyClass o1, MyClass o2) {
int order = Integer.compare(getOrder(o1), getOrder(o2));
return (order != 0 ? order : o1.aString.compareTo(o2.aString));
}
private int getOrder(MyClass m) {
if (m.aString.equals("Hi")) {
return 0;
}
else if (m.aString.startsWith(" ")) {
return 1;
}
else {
return 2;
}
}
};
And call it like this:
Collections.sort(list, myRules);
This works as follows: first, both received strings are mapped to your custom ruleset and subtracted from eachother. If the two differ, then the operation Integer.compare(getOrder(o1), getOrder(o2))1 determines the comparison. Otherwise, if both are the same, then the lexiographic order is used for comparison.
Here is some code in action.
1 Always use Integer::compare rather than subtracting one from the other, because of the risk of erroneous results due to integer overflow. See here.
Yes, that is possible, you have complete control over the compareTo() method. Two things:
Use String#equals instead of == to compare strings
Make sure you check both arguments to compareTo for your exceptional cases.
A concrete way of implementing something where some words are always first and some words are always last, with ordering defined among the exceptions:
Map<String, Integer> exceptionMap = new HashMap<>();
exceptionMap.put("lowest", -2);
exceptionMap.put("second_lowest", -1);
exceptionMap.put("second_highest", 1);
exceptionMap.put("highest", 2);
public int compareToWithExceptionMap(String s1, String s2) {
int firstExceptional = exceptionMap.getOrDefault(s1, 0);
int secondExceptional = exceptionMap.getOrDefault(s2, 0);
if (firstExceptional == 0 && secondExceptional == 0) {
return s1.compareTo(s2);
}
return firstExceptional - secondExceptional;
}

Time complexity of Arrays.equals()

I have two char arrays generated from two strings.I would like to determine whether the arrays are equals.
str1Array = str1.toCharArray();
str2Array = str2.toCharArray();
My understanding is that str1Array.equals(str2Array) will only return true when the array objects are the same object in memory. If I want to check whether each of the indices are the same, I should use Arrays.equals(str1Array, str2Array)
I am wondering about the complexity of this equals method.
I assume it cannot be O(1) because it is not able to evaluate the content equality of the array objects without checking equality for each index. My guess is that it is O(n) where n corresponds to the min(str1Array.length, str2Array.length)
Can anyone verify this or comment otherwise?
Well, let's look at the source code:
public static boolean equals(Object[] a, Object[] a2) {
if (a==a2)
return true;
if (a==null || a2==null)
return false;
int length = a.length;
if (a2.length != length)
return false;
for (int i=0; i<length; i++) {
Object o1 = a[i];
Object o2 = a2[i];
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return true;
}
(It's about the same for the other variations of the method).
As we can see, it's iterating through the array. So it has a worst-case complexity of O(n), where n is the length of the arrays compared. (If the arrays are different sizes, then it exits immediately, making it O(1)).
However, it doesn't always take that long. It does have some preconditions for equality, a null check, and a length check. It also exits as soon as a match is found, so it could take a lot less time.

Why don't Java logical operators && and || work with arrays?

I am effectively trying to write a multiple-bit if-statement in binary. If val is true, I would like to return the correct value of x. However, if val is false, I would like to return all values of the array to be false.
This is effectively the same as checking all values within the array against the value of val. Why doesn't this work?
boolean[] ifStatement(bit0, bit1, bit2, bit3, val) {
boolean[] x = {bit0, bit1, bit2, bit3};
return (x && val);
}
In response to comments asking what I mean by the question, the following is a representation using an 8-bit AND gate in the program Logisim:
I am also aware that it is very easy to do the same thing using a for statement. My question is why is the example code not possible?
Thanks in advance.
The short answer is no. You have check each item. It'd be kind of nice if it did work, but there you have it.
There are, however, special classes like BitSet that provide special functionality for big collections of booleans. You might find one of these useful. Typically not worth the effort for short numbers of booleans, though.
boolean[] x = {bit0, bit1, bit2, bit3};
return (x && val);
Why doesn't this work?
Your proposed meaning of that expression matches the semantics of the standard map higher-order function in the FP paradigm. Interestingly enough, I am not aware of any actual FP language which would have its AND operator overloaded to mean map((applyPartial(AND, val), coll) when one of its operands is a collection.
But, constraining the discussion to Java, such a feature would be deeply incongruent with everything else in it. It would make a logical operator suddenly behave like a batch collection operator; there is nothing even remotely close to that in Java, which is meant to be as unsurprising to beginners as possible, and especially so to people already familiar with C.
BTW you should have at least picked & because && has short-circuiting semantics, something which makes no sense in your proposal.
An array is a type all its own, not a boolean. So you can't use logical operators on an array type.
From your question description, it sounds like you just want to check every value in the array against some baseline boolean. You can do that with a loop over all elements in the array, and if any of don't match up to the baseline, return false.
public boolean ifStatement(boolean base, boolean... values) {
for(boolean value : values) {
if(!(value && base)) {
return false;
}
}
return true;
}
EDIT: After your diagram explained a few things, it seems that a boolean array is the wrong data structure. Why not work with a byte directly? (8 bits = 1 byte)
public byte ifStatement(boolean val, byte value) {
return val ? value : (byte) 0x00;
}
You're either returning value or nothing in your example, so I believe that this would work better.
This doesn't work because the Java compiler doesn't interpret your wishes but adheres to its specification.
And the boolean operators only work with, well, booleans. Arrays of booleans aren't booleans.
Actually you don't need for loop / bitwise operators:
boolean []ifStatement(boolean b1, boolean b2, boolean b3, boolean b4, boolean val) {
if (!val) {
boolean []result = {false, false, false, false};
return result;
} else {
boolean []result = {b1, b2, b3, b4};
return result;
}
}

Most compact way to compare three objects for equality using Java?

What's the most compact code to compare three objects for (semantic) equality using Java? I have a business rule that the objects must be unique i.e. A is different to B, A is different to C and B is different to C.
Assume that the objects are all of the same class and have correctly overridden equals and hashCode methods. A slight wrinkle is that object C could be null—if this is the case then A and B have to be different to each other.
I have some code but it's a bit workmanlike for my tastes.
As the OP said A and B are never null, C may be null, use this:
if(A.equals(B) || B.equals(C) || A.equals(C))
// not unique
and, as others have already suggested, you can put it in a method for reuse. Or a generic method if you need more reuse ;-)
Note that in Java, a feature of equals is that if its argument is null it should not throw, but return false.
Since I never start a Java project without using Apache commons-lang, try ObjectUtils.equals (it's null safe):
if (ObjectUtils.equals(a, b) || ObjectUtils.equals(b, c) || ObjectUtils.equals(a, c)) {
// error condition
}
Put that logic in a generic method, and you'll do even better.
While the business logic allows C to be null, in scenarios like this, it's often better to code defensively and assume that either A or B could be null as well.
You can abstract that method in a utilities method like:
public boolean allUnique(Object... objs) {
Set<Object> set = new HashSet<Object>();
for (Object o : objs)
set.add(o);
return set.size() == objs.length
}
The method may not perform well for small numbers (due to the overhead of creating the Set and the varargs array). However, it grows linearly O(n), and for large values it's better than the quadratic growth of a nested if statements.
boolean areDistinct(Object a, Object b, Object c) {
return (!a.equals(b) &&
(c == null || (!c.equals(a) && !c.equals(b))));
}
As the apache's common.lang3.ObjectUtils.equals() is #Deprecated. Use Objects.equals(aObj,bObj). Comparison should be made with && if you want that all 3 objects are the same. Use || if you want that just one combination of a&b, a&c or b&c is the same.
/**
* Compare 3 objects of the same {#link TYPE}, if they are all equal using {#link Objects#equals(Object, Object)}.
*
* #param aObj the 1st object
* #param bObj the 2nd object
* #param cObj the 3th object
* #param <TYPE> the type of the objects
* #return true if the are all the same
*/
public static <TYPE> boolean equals(TYPE aObj, TYPE bObj, TYPE cObj) {
return Objects.equals(aObj, bObj) && Objects.equals(bObj, cObj) && Objects.equals(cObj, aObj);
}
As long as your objects implement equals, you can use the Stream API to get a distinct set of values, and if that distinct count is 1, they are all the same.
boolean allEqual = Stream.of(obj1, obj2, obj3).distinct().count() == 1
package com.test;
public class Equality {
public static void main(String[] args) {
Boolean flag;
int[] arr={1,1,1,12};
flag=check_equal(arr);
System.out.println(flag);
}
public static Boolean check_equal(int[] arr){
Boolean flag=true;
outerloop:
for(int i=1; i< arr.length; i++)
{
for(int j=1; j< arr.length; j++){
if(arr[i]==arr[j]){
flag=true;
}
else{
flag=false;
break outerloop;
}
}
}
return flag;
}
}

Why is this invalid Java? Type of ternary operator output

Check out this code.
// Print object and recurse if iterable
private static void deep_print(Object o) {
System.out.println(o.getClass().toString() + ", " + o.toString());
boolean iter = false;
Iterable<?> i1 = null;
Object[] i2 = null;
if (o instanceof Iterable<?>) {
iter = true;
i1 = (Iterable<?>) o;
} else if (o instanceof Object[]) {
iter = true;
i2 = (Object[]) o;
}
if (iter) {
for (Object o_ : i2 == null ? i1 : i2) deep_print(o_); // ERROR: Can only iterate over an array or an instance of java.lang.Iterable
}
I know how to solve it. I just want to know why it happens. Shouldn't the compiler simply check all the possible outputs?
The static result type of the expression (i2 == null) ? i1 : i2 is the common ancestor of i1 and i2 which is Object. A for statement requires the static type of the expression to be either an Iterable or an array type. That is not the case, so you get a compilation error.
Now if you are asking why doesn't the compiler deduce that (i2 == null) ? i1 : i2 will always be an array or an Iterable:
The Java language specification (JLS) does not allow this.
If the JLS did allow it (but not require it) then different compilers would behave differently, depending on how good they were at theorem proving. BAD.
If the JLS required it, then the compiler has to incorporate a sophisticated theorem prover`1 (BAD SLOW), and you run into the "minor inconvenience" of solving the Halting Problem2 (BAD BAD BAD).
In actual fact the compiler needs to know which of the two kinds of type the expression has because it needs to generate different code in each case.
Hypothetically, if the Java type system was a bit different, this particular case could be handled better. Specifically, if Java supported algebraic data types then it would be possible to declare o as being "either an object array or an iterable" ... and the for loop would be type-checkable.
1 - Suppose that o had been initialized as o = (x * x < 0) ? new Object() : new Object[0]. Determining that that will always result in an Object[] instance entails a small proof involving the fact that the square of a (real) number is not negative. That's a simple example, it is possible to construct arbitrarily complicated examples requiring arbitrary difficult proofs.
2 - The Halting Problem is mathematically proven to be an incomputable function. In other words, there exist functions where it is mathematically impossible to prove whether or not they terminate.
To illustrate Stephen C's answer, consider the following code:
void test() {
Iterable<Integer> i1 = new ArrayList<Integer>();
Object[] i2 = { 1, 2, 3 };
method1(false ? i1 : i2);
method1(true ? i1 : i2);
}
void method1(Object o) {
System.out.println("method1(Object) called");
}
void method1(Object[] o) {
System.out.println("method1(Object[]) called");
}
void method1(Iterable<?> o) {
System.out.println("method1(Iterable<?>) called");
}
This is the output of test():
method1(Object) called
method1(Object) called
Since method overloading is done at compile-time, you can see that the static type of the ternary operator expression is Object, since the types of the operands differ. Therefore, when you do :
for (Object o_ : i2 == null ? i1 : i2)
you are really asking the compiler to generate a foreach loop over an Object, which is illegal.
in this case, the conditional expression has the type of the least upper bound of the two types, which is Object, and the foreach loop does not work on type Object
You really should add two overloaded deepPrint( Object[] ) and deepPrint(Iterator i) methods and do the dispatch in your deepPrint(Object object). Yes because of the nature of how the for/each loop works you will need to copy and paste the same code with minor changes.
Trying to put all that into one big method is a smell.
You can avoid the code duplication by wrapping the Object[] in an Arrays.asList(Object[]) and then have an Iterable in all cases. Yes its slightly slower than working on an array, but it has the advantage of being DRY, which should always be the first approximation, IMHO.
So you would end up with something like this:
Iterable<?> it = null;
if (o instanceof Iterable<?>) {
it = (Iterable<?>) o;
} else if (o instanceof Object[]) {
it = Arrays.asList((Object[]) o);
}
if (it != null) {
for (Object o_ : it) deep_print(o_);
}
For simplicity's sake (see Stephen C's answer for how it is simpler for compiler writers, but it is arguably a simpler language design as well) the ternary operator assumes the type to be the lowest common demoninator between the two return types, rather than accomidating one of the two return types. Consider the case of a method overloading. The right method is determined and compile time. This means that the compiler has to be able to make a decision about the declared return type at compile time, and can't delay that decision to run time.

Categories