Most compact way to compare three objects for equality using Java? - 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;
}
}

Related

Error when trying to implement 2 methods in another method - java

I have 2 methods isArithmetric and isRelational, both of these methods are used to see if e belongs to a certain instance of a class (eg. if e is a type like 2 + 3 then its in isArithmetric and is an instanceof Additiona, and if e is like 3 > 2 then its in isRelational and is an instanceof GreaterThan). I need to implement the isTypeCorrect method which I know uses the two methods mentioned above to see if when used, returns true if e is either one of the two methods above, and false otherwise. The thing is, I don't know how to implement isTypeCorrect, I tried to call the method from isTypeCorrect and used an if statement but it would not work. Any help would be appreciated.
Code:
private boolean isArithmetic(Expression e) {
return
e instanceof Addition
|| e instanceof Subtraction
|| e instanceof Multiplication;
}
/**
* sub-routine that can be used to check if this is type correct
* true if e is one of the three classes, or their subclasses (if any)
*/
private boolean isRelation(Expression e) {
return
e instanceof Equal
|| e instanceof GreaterThan
|| e instanceof LessThan;
}
/**
* If this collector is AddAll or TimesAll, then all stored expressions must be integer expressions
* (i.e., Addition, Subtraction, Multiplication).
* If this collection is ConjoinAll or DisjoinAll, then all stored expressions must be boolean expressions
* (i.e., GreaterThan, LessThan, Equal)
* #return whether it is possible to evaluate the stored collection of expressions.
*/
boolean isTypeCorrect() {
}
Look at this code.
boolean isTypeCorrect() {
boolean result = false;
AddAll a = new AddAll();
TimesAll t = new TimesAll();
if (this.isArithmetic(a) || this.isRelation(t)) {
result = true;
}
return result;
}
a and t are new instances of AddAll and TimesAll respectively with no changeable arguments to a constructor. How could they ever be anything different each time you invoke this method. In fact, they are going to be local values and go out of scope when you exit the method. I can't tell what is going on but it looks like a design flaw.

A question about source code of Collection.contains(Object o) in ArrayList;

The following is the source code for Conlletion.contains(Object o) in ArrayList:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
I want to know why not type check first,for example:
public boolean contains(Object o) {
if(o.getClass() != elementData[0].getClass())
return false;
return indexOf(o) >= 0;
}
This is more efficient when o is a different type,isn't it?
(ps:Sorry, my English is not very good, I don't know if I speak clearly)
Since elementData is always allocated as an Object[], the expression elementData.getClass().getComponentType() is the same as Object.class, so if (o.getClass() != elementData.getClass().getComponentType()) would pretty such always be true, i.e. contains() would pretty such always return false.
Your suggestion wouldn't work, that's why it's not done that way.
Besides, even if you could, it still wouldn't work, because the values of a Collection object can be any subclass of the type specified for the collection.
E.g. an ArrayList<Number> can contain a mix of Integer, Long, Double, ... objects, so even if elementData.getClass().getComponentType() would have returned Number.class, it would still be a bad type check.
I am only guessing but I think it was an api design decision.
Since Java supports overwriting the equals method- it is up to the programmer to decide what it means for two objects to be equal. In theory, two objects of different types can be considered equal in a certain domain. It is true that checking for type equality is common when implementing equals, but it is not a mandatory. Since contains is a method for the most general case, no assumptions were made regarding the domain it would be called in.

Java-trouble with not equal to

I am trying to solve a question. But the program control is going into the if statement even when both the numbers I check are the same which is not supposed to happen. What is the reason?
static int lonelyinteger(int[] a) {
Integer[] b=new Integer[a.length];
for(int i=0;i<a.length;i++){
b[i]=new Integer(a[i]);
}
int val=0;
Arrays.sort(b);
boolean flag=false;
for(int i=0;i<a.length-2;i+=2)
if (b[i]!=b[i+1]){
val=b[i];
flag=true;
break;
}
if(flag==true)
return val;
else
return b[a.length-1];
You are using != on Integer objects. This will only work with integer values between -128 and 127 (reference) because these are cached by the JVM. But it won't work for larger/smaller values. Instead use .equals
if (!b[i].equals(b[i+1])){
val=b[i];
flag=true;
break;
}
As correctly pointed out by Jesper in the comments, the cache used for Integer objects by the JVM is not used when you force the JVM to create new Integer objects through the explicit call of the constructor as in new Integer(value). Calling the constructor will create new Integer instances instead of returning the cached Integer instances, which means that != and == which check whether the two objects are the same instance will always think the instances are different.
1) Do not use new Integer() use Integer.valueOf() instead.
2) Use Object.equals() when comparing objects.
if (b[i]!=b[i+1]) {
...
}
should be
if (!b[i].equals(b[i+1])) {
...
}

How to combine equality operators in an if statement in 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);

compacting an array in java by removing certain objects

For my computer science class we are supposed to take an array of objects {A,C,D,C,C,F,C,G} and sets all elements of a certain object to null. Object is C: {A,null,D,null,null,F,null,G}
Then we are supposed to move all the remaining object to the front of the array {A,D,F,G,null,null,null,null}...
So far I tried this but I cant find the problem with my method:
public static void compact (Object[] vec, Object item) {
int a=0;
for(int i=0; i < vec.length; i++)
{
if(vec[i]==item)
{
vec[i] = null;
}
else
{
vec[i]=vec[a];
a++;
}
}
for(int b=a; b < vec.length-(a-1); b++)
{
vec[b]=null;
}
}
Help please?
if(vec[i]==item)
Never use == for comparing objects, use equals() (and, when you define a new class, take care in implementing equals() and hashCode() in a practical way)
Of course there may be other problems, but since you are not even telling what it is failing I won't care much.
I think you want equals() rather than == unless testing for null. You are using an object.

Categories