So Im having a problem with my equals class
public boolean equals(Object other) {
if (other.equals(this.numerator) && other.equals(this.denominator))
return true;
else
return false;
}
it gives me the result of 9/2 eq 9/2= false.
(Rest of my code for referees )
https://gist.github.com/anonymous/6604f427cc9d17391478
What am i doing wrong?
I edited the code but still and dealing with an error of boolean and int
public boolean equals(Object other) {
if (other.equals(this.numerator) == getNumerator() && other.equals(this.denominator)== getDenominator())
return true;
else
return false;
}
When implementing equals, before checking if the objects are equal you should consider the next scenarios:
The two are actually references to the same object
The other object is null
The other object is an instance of a different type
and when checking equality between the two objects you should consider the nullness of every field involved in the comparison too. In most IDEs equals can be generated automatically, in eclipse:
Alt + Shift + s --> Generate hashCode() and equals()
the next is generated by eclipse:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
A other = (A) obj;
if (denominator == null) {
if (other.denominator != null)
return false;
} else if (!denominator.equals(other.denominator))
return false;
if (numerator == null) {
if (other.numerator != null)
return false;
} else if (!numerator.equals(other.numerator))
return false;
return true;
}
return
(other.numerator.equals(this.numerator)
&&
other.denominator.equals(this.denominator))
Of couse this doesn't consider that 1/2 == 2/4.
Related
This is probably a trivial question but I'm having some problems (Probably due to my lack of knowledge and experience and I can't seem to find example code anywhere as I'm not too sure what to search for).
I have a list of Custom objects, List<StackTrace>. I want to remove all duplicate objects from this list based only on two properties firstLineOfStackTrace and typeOfException.
I asked a similar question the other day and someone mentioned about overriding equals and hashCode. I did a bit of research and I think I have done that now.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstLineOfStackTrace == null) ? 0 : firstLineOfStackTrace.hashCode());
result = prime * result + ((typeOfexception == null) ? 0 : typeOfexception.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LogEntry other = (LogEntry) obj;
if (firstLineOfStackTrace == null) {
if (other.firstLineOfStackTrace != null)
return false;
} else if (!firstLineOfStackTrace.equals(other.firstLineOfStackTrace))
return false;
if (typeOfexception == null) {
if (other.typeOfexception != null)
return false;
} else if (!typeOfexception.equals(other.typeOfexception))
return false;
return true;
}
My question is how do I actually use these overridden methods in my code to give me an output which has no duplicates?
I have a class with a for-loop within the equals/hashCode:
class User {
private List<Task> tasks;
private ZonedDateTime date;
#Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + (date != null ? date() : 0);
for (var task : tasks) {
hash = 31 * hash + task.hashCode();
}
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final User other = (User) obj;
if (tasks.size() != other.tasks.size()) return false;
// needed?
for (int i = 0; i < tasks.size(); i++) {
if (!tasks.get(i).equals(other.tasks.get(i))) {
return false;
}
}
return Objects.equals(timeStamp, other.timeStamp) && Objects.equals(tasks, other. tasks);
}
}
I am used to have this version (version 2) of equals/hashCode, which is shorter and faster:
#Override
public int hashCode() {
return Objects.hash(date, tasks);
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final User other = (User) obj;
return Objects.equals(timeStamp, other.timeStamp) && Objects.equals(tasks, other. tasks);
}
Can I replace the former equals/hashCode with the version 2 without worrying about correctness?
Are both versions return the same result?
To sum up:
for typcial List implementation we can use version 2 instead of version 1.
One additional question related to this:
Will version 2 be also valid, if the property task is not a List but a Stream? (Stream<Task> tasks).
It depends on the specific List implementation.
Let's look at what Object.equals does:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
So it checks for a couple of trivial cases, then calls a.equals(b), which means that it will call the equals method of your list. But if you're using some custom List or just some list that doesn't compare the elements one by one, then the two implementation will be different.
For any sane implementation, equals should iterate over the elements and compare each one using equals. This is what AbstractList does.
Also note that your hash code will probably change between implementations.
Version 2 will work just fine, though it will return slightly different hash codes.
I have a bean with 4 attributes:
user
institutionId
groupId
postingDate
I use Eclipse to generate equals and hashcode but the resulting code is not pretty. Is there a compact way to do the same? Assuming I want equals & hashcode to use all the attributes or a subset of them.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((groupId == null) ? 0 : groupId.hashCode());
result = prime * result + ((institutionId == null) ? 0 : institutionId.hashCode());
result = prime * result + ((postingDate == null) ? 0 : postingDate.hashCode());
result = prime * result + ((user == null) ? 0 : user.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManGroupKey other = (ManGroupKey) obj;
if (groupId == null) {
if (other.groupId != null)
return false;
} else if (!groupId.equals(other.groupId))
return false;
if (institutionId == null) {
if (other.institutionId != null)
return false;
} else if (!institutionId.equals(other.institutionId))
return false;
if (postingDate == null) {
if (other.postingDate != null)
return false;
} else if (!postingDate.equals(other.postingDate))
return false;
if (user == null) {
if (other.user != null)
return false;
} else if (!user.equals(other.user))
return false;
return true;
}
In Java 7
public int hashCode() {
return Objects.hash(groupId, institutionId, postingDate, user);
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
// cast to correct class
Target o = (Target)obj;
return Objects.equals(groupId, o.groupId) &&
Objects.equals(institutionId, o.institutionId) &&
Objects.equals(postingDate, o.postingDate) &&
Objects.equals(user, o.user);
}
You could compact the code down, but the odds are far higher that you would introduce bugs than that you would do anything useful. All the parts of the equals and hash code method are there for a reason.
If it's bothering you most IDEs have a folding editor, just click the little yellow box (usually) and all the contents of the method get hidden away.
Instead of using the eclipse generated code, you can use Apache-common-langs(http://commons.apache.org/proper/commons-lang/) class HashCodeBuilder and EqualsBuilder to do this:
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this);
}
hashCode:
Either:
#Override
public int hashCode() {
return Objects.hash(user, institutionId, groupId, postingDate);
}
Or:
#Override
public int hashCode() {
int result = 17;
result = 31 * result + Objects.hashCode(user);
result = 31 * result + Objects.hashCode(institutionId);
result = 31 * result + Objects.hashCode(groupId);
result = 31 * result + Objects.hashCode(postingDate);
return result;
}
Equals:
public boolean equals(Object obj){
if (obj == this){
return true;
}
if (! (obj instanceof ManGroupKey)){
return false;
}
ManGroupKey other = (ManGroupKey) obj;
return Objects.equals(user, other.user)
&& Objects.equals(institutionId, other.institutionId)
&& Objects.equals(groupId, other.groupId)
&& Objects.equals(postingDate, other.postingDate);
}
You can at least remove one level of nesting by removing the other.x != null check.
Comparing a value in this way: x.equals(y) will always return false when y is null.
Aside from that: the .equals() method is a good example where a bit of reflection can be handy, possible extracted out into a generic utility method. All you have to do is run through the different fields and see if they're equal in the two objects, that can be done in a few lines.
Obviously that is only feasible when you actually want to compare each field (or you'll have to add some additions to it which let you choose the fields).
I think the library, that can suite you is apache common. It provides EqualsBuilder and HashCodeBuilder classes, that do exactly what you are looking for.
Consider this question for details: Apache Commons equals/hashCode builder
Here are some code snippets:
public class Bean{
private String name;
private int length;
private List<Bean> children;
#Override
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();
}
#Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return new EqualsBuilder()
.append(name, other.name)
.append(length, other.length)
.append(children, other.children)
.isEquals();
} else{
return false;
}
}
}
I need to remove an element of the array based on a match.
Here is my method to remove the event.
public boolean removeEvent(int year, int month, int day, int start, int end, String activity)
{
Event newEvent = new Event(year, month, day, start, end, activity);
for (int i = 0; i < 5; i++)
{
if (newEvent.equals(events[i]))
{
events[i] = null;
newEvent = null;
numEvents--;
}
}
When I try
calendarTest1.removeEvent(2000, 1, 1, 1, 1, "Cal Test 1");
nothing happens. I have an element in my array with those values but it does not change that element to null.
This is for homework so I don't really want to be told how to do it, just why this does not work. Thank you.
Here is my equals method:
public boolean equals(Object obj){
Event someEvent = (Event) obj;
if(
this.date == someEvent.date
&&
this.start == someEvent.start
&&
this.end == someEvent.end
&&
this.activity.equals(someEvent.activity))
if(obj == null)
return false;
if(obj instanceof Event)
return true;
else
{
return false;
}
}
I have tried a lot of different things but I still get the NullPointerException Error
your overridden equal method shoud be somethig like below
#Override
public boolean equals(Object o) {
// If the object is compared with itself then return true
if (o == this) {
return true;
}
/* Check if o is an instance of Event or not
"null instanceof [type]" also returns false */
if (!(o instanceof Event)) {
return false;
}
// typecast o to Event so that we can compare data members
Event e = (Event) o;
// Compare the data members and return accordingly
return year==e.year && month== e.month && day==e.day && start == e.start && end == e.end && activity.equals(e.activity);
}
}
You are comparing two instances in this if event[i] has Event instance then comparison way is different then strings comparison.
You need to override equals method in you class ex:
#Override
public boolean equals(Object ob) {
if (ob == null)
return false;
if (ob instanceof Event) {
Event e = (Event)ob;
return this.someStringValue.equals(e.someStringValueItHas); // compare all values you want like this
}
return false;
}
here we check correct instance of class then its properties if they are equal or not.
is your equals method checking for all the attributes?
public boolean equals(Object o){
if(o == null) return false;
if(o instanceOf Event){
Event givenObject = (Event) o;
if(this.year == givenObject.year)
if(this.month == givenObject.month)
.....
.....
if(this.activity.equals(givenObject.activity)){
return true;
}
}
return false;
}
I'm currently revising for an exam. On a past paper there was the question,
Override the equals method in the following class. The method shall check for
content equality of the whole state.
class Employee
{
String firstName;
int age;
}
[2 marks]
I did some fiddling for the right answer and have come up so far with this. Is there a simpler way to answer the question and is this right? Many thanks for help.
public class Employee
{
int age;
public boolean equals(Object obj)
{
if(this == obj)
{
return true; //Reference equality.
}
if(!(obj instanceof Employee))
{
return false; // not the same type.
}
Employee other = (Employee) obj;
return firstName == other.firstName;
return age == other.age;
}
}
Use
return (((this.firstName == null || other.firstName == null)
&& this.firstName == other.firstName)
||
this.firstName.equals(other.firstName))
&& age == other.age;
This handles null cases too.
One thing to note, and I wouldn't imagine you would get docked for this in an exam...
It's usually poor practice to do an instanceof when the class isn't final. The reason for that is that equals() must be symmetric. Accepting subclasses (who might also implement equals with their own new aspects) could cause it to not be symmetric.
Example (I think the example is the same used in Effective Java 2ed):
class Point {
protected int x, y;
//equals method uses instanceof Point and checks x and y values are the same
}
class ColorPoint extends Point {
protected Color color;
//equals method checks that it's a ColorPoint, that super.equals is true,
//then checks the Color
}
new Point(1, 2).equals(new ColorPoint(1, 2, Color.red)); //true
new ColorPoint(1, 2, Color.red).equals(new Point(1, 2)); //false
It's a very subtle point that even most of the answerers here didn't take into account. But it's the reason that most generators of equals (such as the one in your favourite IDE) tend to do exact class comparison:
if ( this.getClass() != other.getClass() ) {
return false;
}
When the equals method uses instanceof it's usually a good move to document that subclasses must follow the exact same specification.
A couple of points:
You need to check if obj is null.
To compare String contents in Java, use equals(), i.e. firstName.equals(other.firstName). Check to see if firstName is null first.
Here's an improved implementation:
public boolean equals(Object obj)
{
if(obj == null)
{
return false;
}
if(this == obj)
{
return true; //Reference equality.
}
if(this.getClass() != obj.getClass())
{
return false;
}
Employee other = (Employee) obj;
if(firstName == null)
{
if(other.firstName != null)
{
return false;
}
}
else if(!firstName.equals(other.firstName))
{
return false;
}
return age == other.age;
}
EDIT: Updated type comparison to make equals() symmetric in accordance with #Mark Peters' answer.
The String firstName should be compared with .equals(), NOT ==. The == compare is ok for the primitive int age field.
What if both firstNames are identical, yet age is unequal? Shouldn't this fail?
Something like return (firstName.equals(obj.firstName)) && (age == obj.age);
Of course, that doesn't consider the case when this.firstName is null, which would result in a NullPointerException being thrown.
Are the Employees considered equal if both have null firstNames? What if one is null and the other not? Assuming both must be null, or both must be String.equals(), you could use:
return ((null == firstName && null == obj.firstName)
|| (null != firstName && firstName.equals(obj.firstName)))
&& (age == obj.age);
instead of your 2 return statements. The rest looks ok.
public boolean equals(Object o){
if(this==o){ //same instance, no need to check more
return true;
}
if(o instanceof Employee){ //when null this will yield false
Employee other = (Employee) o;
return (this.name == other.name || (this.name != null && this.name.equals(other.name)) && this.age == other.age;
}
return false;
}
To put together in one answer all the parts already mentioned:
public boolean equals(Object obj) {
if(this == obj) {
return true; //Reference equality.
}
if(obj == null || !(obj instanceof Employee))
{
return false; // not the same type.
}
Employee other = (Employee) obj;
return (firstName.equals(other.firstName) && age == other.age);
}
Your last line, the age comparison, is unreachable; you shouldn't use == to compare Strings; and you need to account for null values.
Since the general movement seems to be towards laying it all out for you, here's Eclipse's implementation:
public class Employee {
private final String firstName;
private final int age;
public Employee(final String firstName, final int age) {
super();
this.firstName = firstName;
this.age = age;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Employee other = (Employee) obj;
if (age != other.age) {
return false;
}
if (firstName == null) {
if (other.firstName != null) {
return false;
}
} else if (!firstName.equals(other.firstName)) {
return false;
}
return true;
}
}
And a battery of tests:
import org.junit.Test;
public class EmployeeTest {
#Test
public void testEmployeeEquals() {
final Employee nullNameEmp = new Employee(null, -1);
final Employee empA1 = new Employee("a", 1);
final Employee empA1Clone = new Employee("a", 1);
final Employee empA2 = new Employee("a", 2);
final Employee empB1 = new Employee("b", 1);
final Employee empB2 = new Employee("b", 2);
final Employee subEmp = new Employee("a", 1) {
};
assert !nullNameEmp.equals(empA1);
assert !nullNameEmp.equals(empA1Clone);
assert !nullNameEmp.equals(empA2);
assert !nullNameEmp.equals(empB1);
assert !nullNameEmp.equals(empB2);
assert !nullNameEmp.equals(subEmp);
assert !nullNameEmp.equals(null);
assert !empA1.equals(nullNameEmp);
assert empA1.equals(empA1Clone);
assert !empA1.equals(empA2);
assert !empA1.equals(empB1);
assert !empA1.equals(empB2);
assert !empA1.equals(subEmp);
assert !empA1.equals(null);
assert !empA2.equals(nullNameEmp);
assert !empA2.equals(empA1);
assert !nullNameEmp.equals(empA1Clone);
assert !empA2.equals(empB1);
assert !empA2.equals(empB2);
assert !empA2.equals(subEmp);
assert !empA2.equals(null);
assert !empB1.equals(nullNameEmp);
assert !empB1.equals(empA1);
assert !empB1.equals(empA1Clone);
assert !empB1.equals(empA2);
assert !empB1.equals(empB2);
assert !empB1.equals(subEmp);
assert !empB1.equals(null);
assert !empB2.equals(nullNameEmp);
assert !empB2.equals(empA1);
assert !empB2.equals(empA1Clone);
assert !empB2.equals(empA2);
assert !empB2.equals(empB1);
assert !empB2.equals(subEmp);
assert !empB2.equals(null);
assert !subEmp.equals(nullNameEmp);
assert !subEmp.equals(empA1);
assert !subEmp.equals(empA1Clone);
assert !subEmp.equals(empA2);
assert !subEmp.equals(empB1);
assert !subEmp.equals(empB2);
assert !subEmp.equals(null);
assert nullNameEmp.equals(nullNameEmp);
assert empA1.equals(empA1);
assert empA1Clone.equals(empA1Clone);
assert empA2.equals(empA2);
assert empB1.equals(empB1);
assert empB2.equals(empB2);
assert subEmp.equals(subEmp);
}
}