Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Even though I have two data objects of a custom class which are equal w.r.t all the variables, assertEquals() method is failing. What am I missing here?
For comparing two objects you need to override the equals() method of the Object class.
When you create two objects of a class, say class A, then the objects are different even if they have all the same variables. This is because the equals method or == both check if the reference of the objects are pointing to the same object.
Object o1 = new A();
Object o2 = new A();
o1.equals(o2);
Here the equals method will return false, even if all the fields are null or even if you assign same values to both the objects.
Object o1 = new A();
Object o2 = o1;
o1.equals(o2);
Here the equals method will return true, because the object is only one, and both o1, o2 references are pointing to same object.
What you can do is override the equals method
public class A {
#Override
public boolean equals(Object obj) {
if (obj==this) return true;
if (obj==null || obj.getClass()!=this.getClass()) return false;
return (this.id==((A) obj).id);
}
// You must also override hashCode() method
}
Here we say objects of class A are equal if they have same id. You can do same for multiple fields.
Comparison to check if its equals are not happens with the help of the equals() function. You need to override this method in your custom class.
public boolean equals(Object obj) { }
Please also make sure you override hashCode() method as well.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm writing a simple method to add an object to an ArrayList if it doesn't already contain it. I'm using the .contains method, but for some reason, when I add a duplicate of an object to the ArrayList, the .contains method returns false, even though I have already added the same object to the ArrayList.
This is my City class:
class City {
private String name, country;
//getters, setters, constructor
}
When I have an ArrayList like this:
List<City> destinations = new ArrayList<>();
with one object added to it
destinations.add(new City("Edmonston", "CA"));
If I check if it contains a duplicate object like this, it returns false
destinations.contains(new City("Edmonston", "CA"))
Here's the full code:
Main method
,
Output
City class
Trip class
Thanks for the help!
See the documentation of List#contains given below:
Returns true if this list contains the specified element. More
formally, returns true if and only if this list contains at least one
element e such that Objects.equals(o, e).
Thus, you need to override equals method in class City. You can do it as follows:
#Override
public boolean equals(Object obj) {
City other = (City) obj;
return Objects.equals(name, other.name) && Objects.equals(country, other.country);
}
In order for contains() to work properly, you have to override the equals() and hashCode() methods in your class. If you don't, the base for equality is that the objects referenced are one and the same.
For example:
City c1 = new City("London", "UK") ;
City c2 = new City("London", "UK") ;
System.out.println(c1.equals(c2)) ; // prints false
c2 = c1 ;
System.out.println(c1.equals(c2)) ; // prints true
EDIT: To override the equals() method, see Arvind Kumar Avinash's answer.
The way the contains method works, according to the documentation, is that it uses Objects.equals(o, e) where o is the object you're checking exists in the ArrayList and e is every element in the array.
Objects.equals(a, b) first checks if either of the arguments are null, and then uses a.equals(b) to check if they're the same.
By default, the equals method in the Object just does a == b, which only returns true if a is the exact same object as b, i.e., a and b both refer to the same location in memory and doesn't care about the variables inside the object.
City c = new City("foo", "bar");
c == new City("foo", "bar") //not true
c == c //true
Because of this default implementation of equals:
City c = new City("foo", "bar");
c.equals(new City("foo", "bar")) //not true
c.equals(c) //true
Therefore, you need to override the equals method in your City class so that you can check whether 2 City objects are equal. Arvind Kumar Avinash's answer provides a way to do this.
However, every collection can implement the contains and similar methods differently. HashSets may use the hash code of objects to compare them. Therefore, it's important to also override the hashCode method for your class.
public int hashCode() {
return Objects.hash(name, country);
}
If you want to insert only one City object in your list, use HashSet and override the equals() and hashCode() methods from Object class in your City class.
public static void main(String[] args) {
Set<City> list = new HashSet<City>();
list.add(new City("Edmonston", "CA"));
list.add(new City("Edmonston", "CA"));
list.add(new City("Edmonston", "CA"));
System.out.println(list); //Edmonston in CA
}
And your City class:
class City {
private String name, country;
public City(String s1, String s2) {
this.name = s1;
this.country = s2;
}
#Override
public boolean equals(Object obj) {
if (obj instanceof City)
return this.name == ((City) obj).name & this.country == ((City) obj).country;
else
return false;
}
#Override
public int hashCode() {
return this.country.hashCode() + this.name.hashCode();
}
#Override
public String toString() {
return this.name + " in " + this.country;
}
}
This question already has answers here:
What is the difference between == and equals() in Java?
(26 answers)
Closed 9 years ago.
The equals method compares whether two object values are equal or not. My question is how it compares the two objects? How can it tell the two objects are equal or not? I want to know based on what it compares the two objects. I am not including the hashCode method.
The default implementation, the one of the class java.lang.Object, simply tests the references are to the same object :
150 public boolean equals(Object obj) {
151 return (this == obj);
152 }
The reference equality operator is described like this in the Java Specification :
At run time, the result of == is true if the operand values are both
null or both refer to the same object or array; otherwise, the result
is false.
This default behavior isn't usually semantically satisfying. For example you can't test equality of big Integer instances using == :
Integer a = new Integer(1000);
Integer b = new Integer(1000);
System.out.println(a==b); // prints false
That's why the method is overridden :
722 public boolean equals(Object obj) {
723 if (obj instanceof Integer) {
724 return value == ((Integer)obj).intValue();
725 }
726 return false;
727 }
which enables this :
System.out.println(a.equals(b)); // prints true
Classes overriding the default behavior should test for semantic equality, based on the equality of identifying fields (usually all of them).
As you seem to know, you should override the hashCode method accordingly.
Consider following example,
public class Employee {
String name;
String passportNumber;
String socialSecurityNumber;
public static void main(String[] args) {
Employee e1 = new Employee();
Employee e2 = new Employee();
boolean isEqual = e1.equals(e2); // 1
System.out.println(isEqual);
}
}
In the code at comment //1 it calls inherited equals method from Object class which is simply comparing references of e1 and e2. So it will always give false for each object created by using new keyword.
Following is the method excerpt from Object
public boolean equals(Object obj) {
return (this == obj);
}
For comparing equality check JLS has given equals method to override in our class. It is not final method. JLS doesn't know on what basis programmar wants to make two objects equal. So they gave non-final method to override.
hashcode does not play role to check object's equality. hashcode checks/finds the Bucket where object is available. we use hashcode in hashing technique which is used by some classes like HashMap..
If two object's hashcode are equals that doesn't means two objects are equal.
For two objects, if equals method returns true then hashcode must be same.
You will have to override equals method to decide on which basis you want object e1 and e2 in above code is equal. Is it on the basis of passportNumber or socialSecurityNumber or the combination of passportNumber+socialSecurityNumber?
I want to know based on what it compares the two objects.
Answer is, by default with the help of inherited Object class's equals method it compares two object's reference equality by using == symbol. Code is given above.
logically, equals does not compare objects (however you can do anything with it), it compares values. for object comparison there is '==' operator
I am trying to understand TreeSet. I have created am Employee object and trying to add the employee object to TreeSet. to realize this I have created class called sortName, which sorts the employee objects based on name. and I have written an equals method too (just to understand the execution flow). I read that in TreeSet to add elements in some sorted we must implement comparator interface and overwrite two methods (compare and equals) ofcourse equals is optional. When i try to run the program it works, I observed that the equals method is never invoked, why is that?
Lets draw a comparison between HashSet and TreeSet. in HashSet when the hashCode is same then it checks for equals method, otherwise not. I am interested in knowing how is the working in TreeSet?
Can anyone give me a example where even equals method is invoked for TreeSet?
public int compare(Object Obj1, Object Obj2) {
System.out.println("compare");
if (Obj1 instanceof Employee19 && Obj2 instanceof Employee19) {
Employee19 emp1=(Employee19) Obj1;
Employee19 emp2=(Employee19) Obj2;
return emp1.sname.compareTo(emp2.sname);
}
return 0;
}
public boolean equals(Object obj){
System.out.println("equals");
return true;
}
I even checked this link but that was not what I was looking...
HashSet with two equals object?
The TreeSet doesn't need to use the equals method, because it gets all the information it needs from the Comparator's compare method (or the compareTo method if it is relying on its elements being Comparable). Either way can tell if elements are equivalent, if the appropriate method returns 0.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I understand the basic concept of overriding hashcode and equals in a class , But can anyone give me an example (code) where the equals will fail only because hashcode was not overridden ?
Thanks in advance.
It's not that equals itself will fail - it's that anything that relies on the contract of hashCode and its relationship to equals could fail. Here's an example:
import java.util.*;
final class Person {
private final String name;
public Person(String name) {
// TODO: Nullity prohibition
this.name = name;
}
#Override
public boolean equals(Object other) {
if (other == null || other.getClass() != Person.class) {
return false;
}
return name.equals(((Person)other).name);
}
}
class Test {
public static void main(String[] args) throws Exception {
Person p1 = new Person("Jon");
Person p2 = new Person("Jon");
System.out.println(p1.equals(p2)); // true
Set<Person> people = new HashSet<Person>();
people.add(p1);
people.add(p2);
System.out.println(people.size()); // 2!
}
}
HashSet assumes that because p1.hashCode() isn't the same as p2.hashCode(), the two elements must be unequal, so can both be in the set. That wouldn't happen if hashCode() were appropriately overridden.
Likewise you could have (with the same Person class);
Map<Person, String> map = new HashMap<Person, String>();
map.put(p1, "foo");
System.out.println(map.get(p2)); // null
This would print out "foo" if the two objects returned equal hash codes, as they're meant to - but again, because they don't, the HashMap thinks there's no match.
Eric Lippert's blog post on GetHashCode is a good introduction to this - it's C#-based, but it applies equally to Java.
If your equals is failing it is because you implemented equals wrong.
Here is how to do it correctly:
the answer to What issues should be considered when overriding equals and hashCode in Java?.
but, just for fun here is an example of an equals method that will fail if hashcode is not overridden:
//NEVER DO THIS
#Override
public boolean equals(Object o){
ThisObject obj = (ThisObject)o;
return this.hashCode() == obj.hashCode();
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why .equals method is failing on two same value objects?
This is really simple but I'm obviously missing something pretty big here.
Cat cat1 = new Cat("bob");
Cat cat2 = new Cat("bob");
System.out.println(cat1 == cat2);
//false since these references point to diferent objects
System.out.println(cat1.equals(cat2));
//returns false also??
Cat is just a simple class that only has a name.
What is going on here, how does equals() work? I was under the impression that it compared all the fields of the object. It seems that is not the case.
Do I need to overide it for all my classes?
Yes.
java.lang.Object provides very basic implementations of equals() and hashCode(). In particular, they don't go around reflecting on the type of the instance, which would (1) be dreadfully slow, and (2) carry a significant risk of comparing fields that you for various reasons don't want to compare in an equality comparison.
If you want equals() and hashCode() to actually be useful for comparing value equality (rather than reference equality which == does), you'll need to implement both within your own type.
Note that it's not enough to implement just equals(); while technically that will "work", it has the potential to lead to all kinds of weirdness. The simple rule of thumb is: neither or both, but never only one. And they must work on the same fields; if equals() says two instances are equal, then calling hashCode() on both must return the same value (also see the hashCode() contract).
It's also usually a good idea to override toString() with code to provide a meaningful description of the object in question. While not strictly needed, you only need to hit your head against this once in the debugger to realize the value. (Thanks #JonTaylor for mentioning this highly useful, related tidbit.)
And it's .NET that calls it GetHashCode(), while Java uses only hashCode() as the function name...
You need to override equals inside your Cat class. Default equals compares objects on references.
class Cat {
private String name;
public Cat(String name) {
this.name = name;
}
#Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof Cat))
return false;
Cat c = (Cat) obj;
return this.name == null ? false : this.name.equals(c.name);
}
#Override
public int hashCode() {
return this.name == null ? 31 : this.name.hashCode();
}
#Override
public String toString() {
return "Cat Name :" + name;
}
}
References
equals
hashCode
toString
The equals() provided by java.lang.object compares, simply speaking, a unique identifier for the object, though not entirely accurate you can think of it as a memory location, so it will only be true if you compare an object with itself (i.e. two references to the same object in memory)
You need to implement your own equals() method in your Cat class:
class Cat
{
String name;
#Override
public boolean equals(Cat other)
{
if (this.name.equals(other.name))
return true;
return false;
}
}
It would be wise to override hashCode() also, unless this is just a very basic application for homework or something. Also toString() can be useful to override as well.
http://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html
From [Java Doc]
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
Without overriding the equals() method, the objects are different
Hence
System.out.println(cat1.equals(cat2)); // is false
That is because the == compare references and java.lang.Object.equals() translates to this==o thus return same as == in your case
In the case above you are using new operator to create two different objects hence both return false.
If you want .equals() to work as you are expecting, then override theequals() in your Cat class.