How do I specify both objects when overriding equals method? - java

I'm doing an assignment that asks me to override the equals method of a house class.
The instructions are as follows:
Two houses are equal when their building areas are equal and their pool status is the same
Until now, this is what I've wrote:
#Override
public boolean equals(Object other) {
if (other instanceof House) {
House otherHouse = (House) other;
return otherHouse.calcBuildingArea() == ???
&& otherHouse.mPool == ???
} else {
return false;
}
}
Now I don't know what to write after the == signs. I don't know how to specify the object that calls the method.

If you call a method without specifying an object, the method will get called on the current object. So you can write
return otherHouse.calcBuildingArea() == calcBuildingArea()
&& otherHouse.mPool == mPool;
or if you want to make it nice and clear and explicit, you can write
return otherHouse.calcBuildingArea() == this.calcBuildingArea()
&& otherHouse.mPool == this.mPool;
Note also that this assumes that mPool is of a primitive type or an enum type. If it's a reference type, such as String, you may need to invoke its equals method like
return otherHouse.calcBuildingArea() == calcBuildingArea()
&& otherHouse.mPool.equals(mPool);
or even the more null-friendly
return otherHouse.calcBuildingArea() == calcBuildingArea()
&& Objects.equals(otherHouse.mPool, mPool);

How about this?
return otherHouse.calcBuildingArea() == this.calcBuildingArea()
&& otherHouse.mPool == this.mPool

Related

How can I avoid multiple if else blocks for Object.equals method?

I'm trying to implement this:
public boolean equals(Object o) {
if (o == this) {
return true;
}
if ((null == o) || !(o instanceof Document)) {
return false;
}
Document other = (Document) o;
// compare in a null-safe manner
if (list == null) {
if (other.list != null)
return false;
} else if (other.list == null)
return false;
else if (!(list.size() == other.list.size())
&& !(list.equals(other.list)))
return false;
return true;
where 'list' is a class variable as well as a field of the object 'o'. Please note that the object 'o' has many other fields including booleans and collection too and I need to compare all of them.
I tried finding related answers but most of them recommend switch cases or other Java 8 components which is not relevant to my scenario.
You're greatly complicating things. Writing "equals" is lengthy boring boilerplate, but you're making it even longer.
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Document)) {
return false;
}
Document other = (Document) o;
if (!Objects.equals(list, other.list)) {
return false;
}
return true;
}
All you need per reference field are the three lines above, similarly for primitives (don't forget to handle NaN for floating point).
Your condition is not only much longer, but it also lacks symmetry. This makes it much harder to write and more error-prone.
Anyway, writing "equals" is not something you should do often manually. I recommend using Lombok and there are many more tools, e.g., AutoValue or EqualsBuilder.
A direct rewrite would be:
// compare in a null-safe manner
if (list == null || other.list == null) {
return list == other.list;
} else {
return list.size() == other.list.size() ||
list.equals(other.list));
}
except if the type of list is a standard Java SE List class you can do away with the size() micro-optimization. (A typical `List.equals implementation will do that for you.) So we can rewrite the above as
// compare in a null-safe manner
if (list == null || other.list == null) {
return list == other.list;
} else {
return list.equals(other.list));
}
except that that is what Objects.equals(...) does. So the final rewrite is:
// compare in a null-safe manner
return Objects.equals(list, other.list);
It is unclear if an IDE will generate equals methods test the fields in a null-safe way. But the counterpoint to that is that it is advisable to design your classes so that you don't need to do that. For example, use an empty List rather than a null.

What is wrong with my equals method?

I am writing a Complex number class and my equals method doesn't seem to be working. I'm supposed to be checking to see if two ComplexNum objects are equal to each other and I am always coming across a logic error that always returns false.
public boolean equals(Object x) {
ComplexNum real = (ComplexNum) x;
if (x == null)
return false;
if (x instanceof ComplexNum && this.imag == (real.real)) {
return true;
} else
return false;
}
This is my demo class
ComplexNum y = new ComplexNum(3.0,15.0);
ComplexNum z = new ComplexNum(3.0,15.0);
System.out.println(y.equals(z));
false < -- my output is false no matter what the values are
You're not performing a like-for-like comparison on the real and imaginary components of your complex number.
This would be my implementation:
public boolean equals(Object o) {
if (o instanceof ComplexNum) {
ComplexNum other = (ComplexNum)o;
return (this.real == other.real) && (this.imag == other.imag);
} else {
return false;
}
}
For those arguing that floating point comparison should never use precise tests, IMHO that should be in another method. Java requires that objects that are .equal() have the same .hashCode(), and that would be very hard to arrange with an epsilon comparison.
Because of the above, you will need this, too (other implementations are possible, and the below assumes that your components are double)
int hashCode() {
return Double(this.real).hashCode() ^ Double(this.imag).hashCode();
}
NB: A test for o == null is not necessary in .equals(), because null is not an instanceof ComplexNum.
EDIT for completely strict conformance with the way that .equals() works on Float or Double types (particularly for NaN values) you might want to use this line instead which replaces == with a per-component application of .equals()
return Double(this.real).equals(other.real) &&
Double(this.imag).equals(other.imag);

How can I cast an Object in an equals override method in Java?

I have the following code in a class used to simulate the IRS with employer filings in accordance with the filer. I am required to override the equals class but I keep getting the error saying that the methods I am trying to use cannot be found when called on the casted Object.
#Override
public boolean equals(Object obj) {
if ((this == null )|| (obj == null) || (this.getClass() != obj.getClass()))
return false;
if ((this.sameEmployer((Employer)obj))
&& (this.getEmployeeSSN() == (Employer)obj.getEmployeeSSN())
&& (this.getName() == (Employer)obj.getName())
&& (this.getEmployeeName() == (Employer)obj.getEmployeeName())
&& (this.getEmployeeWages() == (Employer)obj.getEmployeeWages()))
return true;
else
return false;
}
Casting happens after method calls. According to the precedence of operators, () for method calling is at the highest level, 1, while () for casting is at level 3. In other words you are attempting to cast obj.getEmployeeSSN() as an Employer, not obj.
Once you know obj is an Employer, you can place parentheses to force casting first, e.g.
&& (this.getEmployeeSSN() == ((Employer) obj).getEmployeeSSN())
However, it looks like a mess of parentheses. For clarity, just declare an Employer variable, cast it once, then call the methods, passing the Employer variable.
Employer emp = (Employer) obj;
if (this.sameEmployer(emp)
&& ...
For expressions like this:
(Employer)obj.getEmployeeSSN()
The . has higher precedence - "binds tighter" - than the cast. So it's closer to:
(Employer) (obj.getEmployeeSSN())
... whereas you want:
((Employer) obj).getEmployeeSSN()
in order to cast and then call the method. That's most easily done by casting in an earlier line:
public boolean equals(Object obj) {
if (obj == null || this.getClass() != obj.getClass()) {
return false;
}
Employee other = (Employee) obj;
// Now use "other" in the rest of the code:
return sameEmployer(other)
&& getEmployeeSSN() == other.getEmployeeSSN()
...;
}
Note that:
this can never be null, so you don't need to test it
You don't need nearly as many brackets as you had before
I'd strongly encourage you to use braces for all if blocks... you'd be surprised at how easy it is to end up with mistakes otherwise. (There are lots of SO questions which are basically due to that...)
Any time you have:
if (foo) {
return true;
} else {
return false;
}
you should simplify it to:
return foo;
Class Object doesn't have getEmployeeSSN(). What you should have instead is :
(this.getEmployeeSSN() == ((Employer)obj).getEmployeeSSN() //and so forth.
The cast should happen first, then you try to use the method on the casted object
You just have a problem with priority of your operations. The cast to (Employer) will happen after you call the specific methods. To enforce the priority you need to add brackets:
((Employer) obj).getName()
instead of
(Employer) obj.getName()

How do I compare the "state" of two objects of the same type?

I'm supposed to create my own equals() method which overrides the equals(method) of the parent class. This method accepts a Counter object as its argument. In the code below, I want an easy way to determine if the Counter object argument equals the current instance of the Counter class, if that makes sense. I have achieved this in the code below by comparing the fields of each object one by one, but I want a simpler way to do it. Something that looks like this would be nice: "result = (otherCounter == new Counter(min,max) ? true : false);", but I know that's not right and it gets an error. How do I compare the equality of the variables in the two Counter objects, so that c1.equals(c2) will be false if Counter objects c1 and c2 are different?
public boolean equals(Object otherObject)
{
boolean result = true;
if (otherObject instanceof Counter)
{
Counter otherCounter = (Counter)otherObject;
result = (otherCounter.min == this.min) &&
(otherCounter.max == this.max) &&
(otherCounter.currentCount == this.currentCount) &&
(otherCounter.rolloverOccurrence == this.rolloverOccurrence) ? true : false;
}
return result;
}
Operator overloading is not possible in Java.
And to compare two object are equal or not you should use .equals() method no matter what.
Ex: obj1.equals(obj2)
It is because sometimes Java API (ex: Collections) will internally call equals method to sort the collection. So there is no simple way to compare but to use equals()
Your method is just fine like this except for the other answers you got here that state that there is not overloading of operators in Java, the thing with the result = true instead of false and commenting you remember to override hashCode if you didn't already do. Let me give you one more advise. The method can be written in some more compact way:
public boolean equals(Object obj) {
if (!(obj instanceof Counter)) {
return false;
}
Counter other = (Counter) obj;
return other.min == this.min && other.max == this.max &&
other.currentCount == this.currentCount &&
other.rolloverOccurrence == this.rolloverOccurrence;
}

boolean recursion part 2

trying to write a boolean function that returns true if 'm' is a ancestor of the current class. 'm' is an ancestor if it is a mom or dad, or a ancestor of mom or dad.
will this get me there?
public boolean isAncestor(member m){
if (mom == m || dad == m){
return true;
}
else{
if(isAncestor(m.mom) || isAncestor(m.dad)){
return true;
}
}
return false;
}
thanks!
Yes, more or less. What if you get to a layer of the ancestry where mom or dad aren't known, and are null?
public boolean isAncestor(member m){
if (m == null)
return false;
if (mom.equals(m) || dad.equals(m))
return true;
else if(isAncestor(m.mom) || isAncestor(m.dad))
return true;
return false;
}
The logic will get you there, however one must take care with the equal signs.
In Java == compares for equality of instances. Odds are good that over time you will have two instances which are comparatively equal but exist in different instances. If your code has been written to prevent such a thing from occurring, then you don't need to change the == to .equals(...); but, if you didn't put in any safeguards to ensure only one instance of each "same" object exists, then you might want to change the comparison to .equals(...) and implement an custom "public boolean equals(Object other) {...}` method for the base "person" class.
If you're going to use recurrsion, you are going to need to have a stop condition. Does everyone have a mom or a dad? consider this:
public boolean isAncestor(Member m) {
// stop condition
if(this.mom == null && this.dad == null) return false;
// stop condition
if(this.mom == m || this.dad == m) return true;
// loop condition
return mom.isAncestor(m) || dad.isAncestor(m);
}
It might but it is not 100% correct. You should also check if mum and dad exist otherwise you might end up with NullPointerException.
Moreover the others are correct with the == usage, quite suspicious.
When does the recursion stop, if there is no relationship?
Actually, you need a way to know which two members you are comparing for relationship. You'll probably want to do something like this (untested):
/**
* #param m1 the member we want to get ancestry from
* #param m2 the member we presume is an ancestor
*/
public boolean isAncestor(member m1, member m2){
if (m1 == NULL || m2 == NULL) {
return false;
}
if (m1.isMom(m2) || m1.isDad(m2)){
return true;
}
else if(isAncestor(m1.mom, m2) || isAncestor(m1.dad, m2)) {
return true;
}
return false;
}
You'd need to write isMom and isDad to compare the relationship of m2 to m1.

Categories

Resources