This question already has answers here:
Understanding the workings of equals and hashCode in a HashMap
(9 answers)
Closed 4 years ago.
import java.util.*;
class emp{
String city;
String name;
emp(String a, String b)
{
city=a;
name=b;
}
}
public class HelloWorld{
public static void main(String []args){
Set<emp> s = new HashSet<emp>();
emp s1=new emp("bangalore","mukesh");
emp s2= new emp("bangalore","mukesh");
s.add(s1);
s.add(s2);
System.out.println(s1.equals(s2));
System.out.println("finsih");
System.out.println(s);
}
}
i am creating two objects, which are same but they get entered in set and why s1.equals(s2) return false?
It has nothing to do with inserting to set. You need to override equals, for example below is the basic equal method :
#Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Emp)) {
return false;
}
Emp emp = (Emp) o;
return Objects.equals(city, emp.city) &&
Objects.equals(name, emp.name);
}
Follow details , follow the sample here:
https://www.mkyong.com/java/java-how-to-overrides-equals-and-hashcode/
Since you have not overridden equals(), Object#equals is used which by default uses == operator. Since you have created 2 objects with new operator, their refernces are different and hence call to equals() returns false. You can override both equals and hashcode to provide equality:
class emp{
String city;
String name;
emp(String a, String b) {
city=a;
name=b;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof emp)) return false;
emp test = (emp) o;
return Objects.equals(city, emp.city) &&
Objects.equals(name, emp.name);
}
#Override
public int hashCode() {
return Objects.hash(city, name);
}
Now attempting to store the objects will store only one object in the set.
Related
This question already has answers here:
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Closed 10 months ago.
When i compare two instances in java of the same type class, with the same values of their Attributes, why i get false?
I'm new with OOP and don't Understand some OOP logic.
public static void main(String[] args) {
Object o1= new Object(24,"Omar");
Object o2= new Object(24,"Omar");
System.out.println(o1.equals(o2));
}
The equals method returns true if and only if o1 and o2 refer to the same object. And if We want to compare with members variable, we need to override the equals method in our custom class like below:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CustomObjClass obj = (CustomObjClass) o;
return age == obj.age && Objects.equals(name, obj.name);
}
And then it will return true for the below code:
CustomObjClass o1= new CustomObjClass(24,"Omar");
CustomObjClass o2= new CustomObjClass(24,"Omar");
System.out.println(o1.equals(o2)); // return true
By default, the equals operator verifies if the two objects are the same one. So, for example, if we perform these operations:
Object o1= new Object(24,"Omar");
Object o2= o1
System.out.println(o1.equals(o2));
you would get true, as o2 is the same object as o1. In your case, you have two different objects (since you instantiate them with the "new") that have the same content. Therefore, the equal operator returns false. If you want it to return true, you have to override the equals operator and implement your own logic.
The default implementation of equals method compares the reference of both the objects using == operator. You can find the details here. If you want to compare the value of your Class override the equals method.
Example:
public class TestClass {
private int age;
private String name;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TestClass)) return false;
TestClass testClass = (TestClass) o;
return getAge() == testClass.getAge() && Objects.equals(getName(), testClass.getName());
}
#Override
public int hashCode() {
return Objects.hash(getAge(), getName());
}
public TestClass(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I am trying to Implement a class named Parade using an ArrayList, which will manage instances of class Clown. Each Clown needs to be identified by all object data String for their name, int id and double size. I join a new Clown to the end of the Parade. Only the Clown at the head of the Parade (i.e., the first one) can leave the Parade. In addition, I write a method called isFront that takes a Clown as parameter and returns true if the passed clown is at the front of the parade otherwise returns false. Create a test application to demonstrate building a parade of three or four clowns and include your own name. Then, remove one or two, and add another one or two. Also, test the isFront method by passing different clowns to the method.
I have a code but it is not returning true for the isFront method, I am trying to use contains method I also tried to use Comparable interface Clown but it did not work that well. Not sure what to do.
import java.util.ArrayList;
public class Main
{
public static void main(String[] args)
{
Parade circus = new Parade();
circus.addClown(new Clown("Bobby",9,12.0));
circus.addClown(new Clown("Clair", 2, 11.0));
circus.addClown(new Clown("Tony",6,10.0));
circus.addClown(new Clown("Sarah",3,5.0));
circus.display();
System.out.println(circus.isFront(new Clown("Bobby", 9, 12.0)));
}
}
import java.util.ArrayList;
public class Parade
{
private static ArrayList<Clown> parade;
private int top;
public Parade()
{
top=0;
parade= new ArrayList<Clown>();
System.out.println(parade);
}
public void addClown(Clown c)
{
parade.add(c);
top++;
}
public void removeClown() //(Clown c)
{
parade.remove(0);
top--;
}
public void display()
{
System.out.println(parade);
}
public void getData()
{
parade.get(0);
}
public void setData()
{
parade.set(1,new Clown("Claire",2,5.0));
System.out.println(parade);
}
public int getTop()
{
return top;
}
public boolean isFront(Clown c)
{
return !parade.isEmpty() && c.equals(parade.get(0));
}
//exceptions
}
public class Clown
{
private String name;
private int id;
private double size;
public Clown(String name, int id, double size)
{
this.name=name;
this.id=id;
this.size=size;
}
public String getName()
{
return name;
}
public int getId()
{
return id;
}
public double getSize()
{
return size;
}
public String toString()
{
return name.toString() + id + size;
}
public boolean equals(Object o) {
if (o instanceof Clown c) {
return this.getName().equals(c.getName()) && this.getId() == c.getId() && this.getSize() == c.getSize();
}
return false;
}
}
their is not much info in our textbook about this stuff Java FOundations 5th e Lewis like working with objects and arraylists it skips it and assumes you already know it lol..
Firstly, objects in Java are, by default, compared by reference. So, even if you create two Clown objects with the exact same properties, Java sees them as different objects because both those object references are not the same, they are both referring to different memory locations. You can override this behavior and ask Java to compare it as you want by overriding the equals() method of the Object class:
public class Clown {
private String name;
private int id;
private double size;
public Clown(String name, int id, double size) {
this.name=name;
this.id=id;
this.size=size;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public double getSize() {
return size;
}
#Override
public boolean equals(Object o) {
if (o instanceof Clown) {
Clown c = (Clown) o;
return this.getName().equals(c.getName());
}
return false;
}
#Override
public int hashCode() {
return this.getId();
}
#Override
public String toString() {
return name.toString() + id + size;
}
}
This will help with contains()(it internally uses equals()).
Secondly, you can just compare your clown with the first clown to see if it is the one at the front:
public boolean isFront(Clown c) {
return !parade.isEmpty() && c.equals(parade.get(0));
}
The isFront() method will return true if the parade is not empty and the clown c is equal to to the first clown in the parade. get(0) retrieves the first clown in the parade.
As per your comment, if you want that two clowns be equal only if all their properties are equal, change your equals method to:
#Override
public boolean equals(Object o) {
if (o instanceof Clown) {
Clown c = (Clown) o;
return this.getName().equals(c.getName()) &&
this.getId() == c.getId() &&
this.getSize() == c.getSize();
}
return false;
}
The equals() method is of the Object class which is the parent class of all Java classes. It defines how to compare two objects.
Its signature is as follows:
public boolean equals(Object obj)
As we're overriding, its signature must be the same in the derived class, in our case in class Clown. Its parameter is of type Object not Clown. Any type can be converted to Object, if I compare an object of Clown to another type, like:
Clown c = new Clown("X", 1, 10);
if ( c.equals(objectOfAnotherType) ) {..}
it will still work.
So we use the instanceof operator to check if that another object is also a Clown. If it is not an instance of Clown, we return false but if it is, we convert/cast that object to Clown, only then we can call getName() and other getter methods:
if (o instanceof Clown) {
Clown c = (Clown) o; //Casting happens here
return this.getName().equals(c.getName()) &&
this.getId() == c.getId() &&
this.getSize() == c.getSize();
}
return false;
Java 14 introduced a shortcut for this, instead of these steps:
if (o instanceof Clown) {
Clown c = (Clown) o;
we can simply write:
if (o instance of Clown c)
which does the casting for us and stores it in c.
Lastly, I have also overriden Object.hashCode() because you have to when you override equals(), here's why.
What do I need to write inside the " if " statement in order to check if the object's variable (number) is equal to any of the object's variables (number) inside my array?
public class Question{
private int number;
private String questionString;
private int index = 0;
public Question(int number, String questionString){
if(number < 0){
System.out.print("Number cannot be negative!");
}
if(questionString.equals(null) || questionString.trim().isEmpty()){
System.out.print("Question cannot be empty!");
}
this.number = number;
this.questionString = questionString;
}
public boolean equals(Object o){
if(o instanceof Question){
for(int i = 0; i < index; i++){
if(.... ){
}
}
return true;
}
return false;
}
}
Test Class (main Class), ofc not yet completed I just hope it gives you enough information, on how to proceed on my Question class:
public class Test{
String name;
Question[] questions;
public Testi(String name, int nrQuestions){
}
public static void main(String[]args){
}
}
This should do:
public boolean equals(Object o){
if (o == null )
return false;
if(o instanceof Question){
if (((Question)o).number == this.number ){
if (this.questionString.equals(((Question)o).questionString)){
return true;
}
}
}
return false;
}
Be careful though, if you're implementing equals() you should also implement hashCode(). It's your "model" that should make clear when two objects are equal. In your case, I would say that when two Question's number are the same, then the Question is also the same. If not, you should also add questionString to the check
From your last comment, I think I now understand your REAL issue: You tried to use the equals() method to compare an object to an array of objects that you pass to this method, right? The call to equals would look like this:
Question[] questions;
question.equals(questions);
Technically this is possible with Java, but strongly discouraged I would say. equals() should only be used to compare to one object at a time (and stick to the hashCode/equals contract).
So I suggest you to do something like this:
//your application code
public boolean equals(Object obj){
if (obj instanceof Question){
return (((Question)obj).number == this.number);
}
return false;
}
//use this to obey the equals/hashCode contract
public int hashCode() {
return this.number;
}
// your test code -------------
public void testQuestions(Question testAgainstThisObject, Question[] testQuestions) {
for (Question testThisQuestion : testQuestions) {
assertTrue(testAgainstThisObject.equals(testThisQuestion));
}
}
Another way would be to use a specialised method in Question.java, something like this:
public boolean isThisContained(Question[] questions) {
for (Question question : questions) {
if (this.equals(question)) {
return true;
}
}
return false;
}
I was make some code and found that objects ar eno equals - it is trivial question but not understand how default equals works.
class A {
String id;
public A(String id) {
this.id = id;
}
public static void main(String args[])
{
A a = new A("1");
A b = new A("1");
System.out.println(a.id);
System.out.println(b.id);
System.out.println(a.equals(b));
}
}
Result is:
1
1
false
But I want to have a.equals(b) == true why it is false?
Your class currently extends only Object class and in Object class equals method looks like this
public boolean equals(Object obj) {
return (this == obj);
}
What you need is to override this method, for example like this
#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 (id == other.id)
return true;
if (id == null)
return false;
if (other.id == null)
return false;
if (!this.id.equals(other.id))
return false;
return true;
}
Also when you override equals you probably should override hashCode method, but this is not subject of your question. You can read more about it here.
If you don't override equals() on the object, you are comparing two different memory references. So override equals() to compare the id fields.
It overrides Object's equals method by default, it checks the "same object" rather than "same content". If you want to have a.equals(b) == true, you should override it:
#Override
public boolean equals (Object obj) {
if (obj instanceof A) {
A a = (A) obj;
if (id == null) {
return a.id == null;
} else {
return id.equals(a.id);
}
}
return false;
}
----- EDITED -----
you should rewrite an equals() method for your code, as you would a toString() method.
I want to override "public boolean equals(Object obj)" function, for name and age, in my class named MyObject whose structure is given below
public class MyObject{
private String name;
private int age;
}
How can i ?
#balusC :
What about this ?
vo = new MyObject() {
public boolean equals(Object obj) {
return ((MyObject)obj).name().equals(this.getName());
}
vo = new MyObject() {
public boolean equals(Object obj) {
return ((MyObject)obj).age() == (this.getAge());
Your question is a bit vague, but if the sole purpose is to have different sorting algorithms depending on what property you'd like to use, then rather use a Comparator.
public class Person {
private String name;
private int age;
public static Comparator COMPARE_BY_NAME = new Comparator<Person>() {
public int compare(Person one, Person other) {
return one.name.compareTo(other.name);
}
}
public static Comparator COMPARE_BY_AGE = new Comparator<Person>() {
public int compare(Person one, Person other) {
return one.age > other.age ? 1
: one.age < other.age ? -1
: 0; // Maybe compare by name here? I.e. if same age, then order by name instead.
}
}
// Add/generate getters/setters/equals()/hashCode()/toString()
}
which you can use as follows:
List<Person> persons = createItSomehow();
Collections.sort(persons, Person.COMPARE_BY_NAME);
System.out.println(persons); // Ordered by name.
Collections.sort(persons, Person.COMPARE_BY_AGE);
System.out.println(persons); // Ordered by age.
As to the actual equals() implementation, I'd rather let it return true when the both Person objects are techically or naturally identical. You can use either a DB-generated PK for this to compare on technical identity:
public class Person {
private Long id;
public boolean equals(Object object) {
return (object instanceof Person) && (id != null)
? id.equals(((Person) object).id)
: (object == this);
}
}
or just compare every property to compare on natural identity:
public class Person {
private String name;
private int age;
public boolean equals(Object object) {
// Basic checks.
if (object == this) return true;
if (object == null || getClass() != object.getClass()) return false;
// Property checks.
Person other = (Person) object;
if (name == null ? other.name != null : !name.equals(other.name)) return false;
if (age != other.age) return false;
// All passed.
return true;
}
}
Don't forget to override hashCode() as well when you override equals().
See also:
Object ordering
Sorting an ArrayList of objects
Overriding equals() and hashCode()
I'm not exactly sure what you're aiming at with this. The general expectation of equals() is that it returns false for null and objects of other classes and performs value equality on the relevant fields of the class in question.
While you can certainly handle String and Integer in the following way:
public boolean equals(Object o) {
if (o == null) return false;
if (o instanceof String) return name.equals(o);
if (o instanceof Integer) return ((Integer)o) == age;
...
}
this breaks the contract for equals so you can't do it (except not without things going wrong in very weird ways).
equals is an equivalence relation, so it has to be reflexive, symmetric and transitive. The symmetric part here is key, since if a.equals(b) then b.equals(a). Both String and Integer won't do that for you.
If you want just helper functions that check whether the name or the age is equals to a given name/age, then you can do that without using equals():
public boolean equalsName(String name) { return name.equals(this.name); }
public boolean equalsAge(int age) { return age == this.age; }
Just keep it short and simple (aka KISS principle): write setters and getters. Something like in the following example:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
And then in the method you need to do the check you can write:
Person person = new Person();
if(person.getName().equals("Something")) doThis();
if(person.getAge() == 1337) doThat();
Not sure what you mean by "multiple equals()". If you want compare both your fields, you just need to override the equals method like this,
public boolean equals( Object o )
{
if ( o != null && o instanceof MyObject )
{
MyObject m = (MyObject) o;
if (this.name == null)
return false;
return this.name.eqauls(m.name) && this.age == m.age;
}
return false;
}
/// Compute a hash code for the pair.
public int hashCode()
{
int code = name == null ? 0 : name.hashCode();
return code ^ age;
}
It's a good practice to change hashCode whenever you change equals so HashMap works efficiently with your object.
if you do want to override equals, it should look something like this:
static private <T> boolean checkEquals(T t1, T t2)
{
return (t1 == null) ? (t2 == null) : t1.equals(t2);
}
#Override public boolean equals (Object o)
{
if (o instanceof MyObject)
{
MyObject obj = (MyObject)o;
return checkEquals(this.name, obj.getName())
&& this.age == o.getAge();
}
else
return false;
}
#Override public int hashCode()
{
// implement hashCode
}
You need to override both hashCode() and equals() or neither. And you also should make sure your class is final, otherwise there are potential pitfalls with equals.
public class MyObject {
private String name;
private int age;
#Override
public boolean equals(Object o){
if(o instanceof MyObject){
MyObject otherObject = (MyObject)o;
if(name == null){
return otherObject.name == null && otherObject.age == age;
} else {
return name.equals(otherObject.name) && otherObject.age == age;
}
} else {
return false;
}
}
// When we overriding equals it is a good practice to override hashCode
// for consistecy
#Override
public int hashCode(){
int nameCode = (name == null) ? 0 : name.hashCode();
// See Item 9 in book Effective Java 2nd Edition
return 31 * nameCode + age;
}
}