I have created a Employee class with 3 parameters.
Requirement: Search based on Name. This is a case where all employees have a unique name. Its mandatory to add the objects with key as id. There are rare cases where it is required to search based on name.
What i have done :
Within the class I am overriding hashCode and Equals method.
I am adding a list of these objects into the hashmap with id as key and value as Employee object
But while adding or searching from a hashmap both the methods do not get called
So what is the use of these methods in terms on hasmap?
Employee Class
public class Employee {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int hashCode() {
return name.hashCode();
}
public boolean equals(Employee emp) {
if (emp == null)
return false;
else if (emp.name.equalsIgnoreCase(this.name))
return true;
else
return false;
}
}
Main Method:
public class HashMapTest {
public static void main(String[] args) {
Employee emp1=new Employee();
emp1.setId(1);
emp1.setName("Maclean");
emp1.setAge(24);
Employee emp2=new Employee();
emp2.setId(2);
emp2.setName("Sampath");
emp2.setAge(25);
Employee emp3=new Employee();
emp3.setId(3);
emp3.setName("Achar");
emp3.setAge(27);
Employee emp4=new Employee();
emp4.setId(4);
emp4.setName("Sudheer");
emp4.setAge(25);
Employee emp5=new Employee();
emp5.setId(5);
emp5.setName("Kunder");
emp5.setAge(25);
HashMap<Integer, Employee> empmap=new HashMap();
empmap.put(emp1.getId(), emp1);
empmap.put(emp2.getId(), emp2);
empmap.put(emp3.getId(), emp3);
empmap.put(emp4.getId(), emp4);
empmap.put(emp5.getId(), emp5);
Employee emp=new Employee();
emp.setName("Maclean");
System.out.println(empmap.containsValue(emp));
System.exit(1);
}
}
Update Solution:
Thanks for all the answers.
1. hashCode method gets called only if the Key is a object and the method exists within the Key Class
2. Equals(Employee emp) is causing function overloading instead of overriding. I should have used equals(Object o)
Changes in the code to resolve the issue
@Override
public boolean equals(Object o) {
if (o == null)
return false;
if (!(o instanceof Employee))
return false;
Employee emp = (Employee) o;
if (emp.name.equalsIgnoreCase(this.name))
return true;
else
return false;
}
You are not overriding Object.equals(Object o), which you need to do. You are overloading it. That's why it's not being called.
Try this equals() instead:
public boolean equals(Object o) {
if (o == null)
return false;
if (!(o instanceof Employee))
return false;
Employee emp = (Employee) o;
if (emp.name.equalsIgnoreCase(this.name))
return true;
else
return false;
}
Within the class I am overriding hashCode and Equals method. [...] But while adding or searching from a hashmap both the methods do not get called So what is the use of these methods in terms on hasmap?
If you have a Map<Key, Value>
, and you call put
or get
on that map, then hashCode
and equals
are called on the Key
class, not on the Value
class.
In your case, that means that if you do empmap.put(emp1.getId(), emp1);
then it checks the hash of emp1.getId()
and whether that's already in the map. So it's normal that those methods are not called on your Employee
class.
Also, if id
is the "unique" attribute, then Employee.hashCode
should probably be based on that (and equals
, too, to be consistent with hashCode
), and as noted in another answer, Employee.equals
should accept any Object
as parameter.
I did not test, but try it with
HashMap<Integer, Employee> empmap=new HashMap<>();
or even
HashMap<Integer, Employee> empmap=new HashMap<Integer, Employee>();
This can be done very nicely in Java 8 using streams.
empmap.values().stream().anyMatch(emp.getName().equals(searchedName));
This takes the set of all entries in the map and see if the stream matches any entry that has a name equal to your searchedName
.
In a comparable you can also fetch all matching names by using Stream.filter()
Implementing a different version of equals/hashcode is tricky because it changes the behavior of the class in many ways.
The easiest solution for your problem is to add this method to the Employee class. Silently, HashMap uses the equals(Object o) of a value object (in this case Employee) for checking the existence of that object.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (name != null ? !name.equals(employee.name) : employee.name != null) return false;
return true;
}
Be careful, This implementation of equals(Object o) just works on the name and it does not check other fields.
Employee emp=new Employee();
emp.setId(10);
emp.setName("Maclean");
emp.setAge(240);
System.out.println(empmap.containsValue(emp));
System.out.println(emp1.equals(emp));
is
true true
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.