boolean recursion part 2 - java

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.

Related

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 do I specify both objects when overriding equals method?

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

Not sure how to complete this equals method

Could someone help me with this question please? I've tried looking up other examples of this to find what I need to do and keep running into something called and EqualsBuilder, is that what I need to use? Do I need to have it call on equals again if it satisfies neither of the IFs?
The following code contains a class definition and an incomplete method definition. The equals method is used to compare Buildings.
It is intended to return true if Buildings have the same names and number of floors (but are not necessarily the same Building) and false otherwise.
public class Building {
private String name;
private int noOfFloors;
public boolean equals (Object rhs) {
if (this == rhs) {
return true;
}
if (!(rhs instanceof Building)) {
return false;
}
Building b = (Building) rhs;
// missing return statement
}
}
public boolean equals (Object rhs) {
if (this == rhs) {
return true;
}
if (!(rhs instanceof Building)) {
return false;
}
Building b = (Building) rhs;
// This is what you're supposed to add. It will return true only if both
// object's attributes (name and number of floors) are the same
return this.name.equals(b.name) && this.noOfFloors == b.noOfFloors;
}
The only thing that you have to test for now is the fields of both objects. If they are equal, then you should return true, if at least one of them is not then you should return false.
Since your fields in that case are int and Stringyou can use == for the integer field and .equals() for the String field.
Something like this should do the job just fine:
if(this.name.equals(b.name) && this.noOfFloors == b.noOfFloors){
return true ;
}
else{
return false;
}
After the instanceOf tests you want to compare the fields of the object to the other object. Something like Objects.deepEquals() should do the trick for you nicely.

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()

An efficient equals(Object o) implementation

I read this SO post after I wrote out the title but still decided to go through with the question on bug-proof implementations of equals in Java. This is my normal implementation
#Override
public boolean equals(Object o){
if(o == null) return false;
if(o instanceof CompositePk == false) return false;
if(this == o) return true;
CompositePk that = (CompositePk)o;
return new EqualsBuilder().append(this.id, that.id)
.append(this.bucketId, that.bucketId)
.isEquals();
}
using Apache's EqualsBuilder to do the mundane stuff. Even easier than this is my Netbean's automatically generated equals(o) implementation
#Override
public boolean equals(Object obj){
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TemplatesWrapper other = (TemplatesWrapper) obj;
if (this.timeAdded != other.timeAdded && (this.timeAdded == null || !this.timeAdded.equals(other.timeAdded))) {
return false;
}
return true;
}
I take these from 2 diff projects but they both try to accomplish the same thing but using diff approaches. Which style would you rather or are there any flaws you spot?
First of all, there's no need to test for null, then test for instanceof, since foo instanceof Bar evaluates to false when foo is null.
It's weird to compare the result of the instanceof operator to false, since instanceof is a boolean operation.
Comparing classes with getClass() is at best controversial. Joshua Bloch, who wrote much of the Java collections framework and a lot of other important stuff besides, says
This technique ("getClass-based equals
methods") does satisfy the equals
contract, but at great cost. The
disadvantage of the getClass approach
is that it violates the "Liskov
Substitution Principle," which states
(roughly speaking) that a method
expecting a superclass instance must
behave properly when presented with a
subclass instance. If a subclass adds
a few new methods, or trivially
modifies behavior (e.g., by emitting a
trace upon each method invocation),
programmers will be surprised when
subclass and superclass instances
don't interact properly. Objects that
"ought to be equal" won't be, causing
programs to fail or behave
erratically. The problem is
exacerbated by the fact that Java's
collections are based on the equals
method.
You should use instanceof instead of comparing via getClass() unless you have some specific technical reason not to.
After establishing that the other object is comparable to this, you then compare primitives with == and objects with equals. It's more complicated if any of your member objects can be null; you must then write verbose clauses to compare possibly null things to each other (or write a bothNullOrEqual(Object a, Object b) method).
The EqualsBuilder approach looks bogus to me, but that's just a "smell", which I won't argue against technically. In general, I don't like extra method calls in a method that may be called frequently.
The Apache one is bogus because it tests for null and uses the getClass() comparison.
Here's mine:
#Override
public boolean equals(final Object o) {
if (!(o instanceof MyClass))
return false;
final MyClass om = (MyClass)o;
// compare om's fields to mine
}
I would do it this way:
public boolean equals(Object ob) {
if (ob == null) return false;
if (ob == this) return true;
if (!(ob instanceof MyClass)) return false; // OR
if (ob.getClass() != getClass()) return false;
// check relevant members
}
The two lines in the middle are different. One allows for subclasses to be equal (the first one), the other doesn't. Use whichever one is appropriate.
To give you an example, Java's AbstractList class will probably use the second form, because the exact implementation of List is irrelevant. what matters is if the members are equal and in the same position.
Conversely, a Person class should use the first form (instanceof) because if there is a Student subclass and you call Person.equals(Student) it may return true without checking the extra fields in Student whereas Student.equals(Person) will probably return false. If equals() isn't commutative, you're asking for trouble.
I tend to use equals() methods generated by my IDE (IntelliJ IDEA) rather than creating an unnecessary dependency to some Apache library for little gain.
Apache's is better than yours or cletus'.
As far as my vague memory suggests, there is a problem with using instanceof in equals; I can't quite put my finger on why yet, perhaps someone will elaborate. I could be wrong.
-- Edit:
As Chris and Steve helpfully explain below, I was thinking of the "symmetric property" of equals implementation. On this basis, I can back up my claim of prefering the Apache implementation :)
Honestly, the less code you have to write, the better off you are (in most cases).
The code that's generated has been debugged and used by many MANY people. You might as well use what's generated (and if you need to enhance the performance, do so).
The advantage of using the generated code: any time your instance fields changes (and this generated code wasn't modified), you can simply regenerate code.
Sometimes, it's easier to think about maintainability. Rule of thumb: the less code you write yourself, the less you have to debug. If the generated code doesn't take a huge performance hit, generate it!
Explanation: When overriding the equals method, the hashCode() method must be overrided too. So, considering a class with 3 properties as show below and considering that all the properties are significant to equality, the equals() implementation must test all these fields. The order of conditionals isn't important, but all the fields must to be tested for equality to consider the equality between objects at all.
public class SampleClass {
private Long id;
private String description;
private Date creation;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((creation == null) ? 0 : creation.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
boolean isEquals = true;
if (this == obj) { isEquals = true; }
else if (obj == null) { isEquals = false; }
else if (getClass() != obj.getClass()) { isEquals = false; }
else {
SampleClass other = (SampleClass) obj;
if (creation == null) {
if (other.creation != null) isEquals = false;
} else if (!creation.equals(other.creation)) {
isEquals = false;
} else if (description == null) {
if (other.description != null) isEquals = false;
} else if (!description.equals(other.description)) {
isEquals = false;
} else if (id == null) {
if (other.id != null) isEquals = false;
} else if (!id.equals(other.id)) {
isEquals = false;
}
}
return isEquals;
}

Categories

Resources