简体   繁体   中英

How to check if a string exists in a object which is stored in a hashmap?

I have created a Employee class with 3 parameters.

  1. Id
  2. Name
  3. Age

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM