📜  关于 hashCode 和 equals 方法的有趣面试问题

📅  最后修改于: 2022-05-13 01:54:57.818000             🧑  作者: Mango

关于 hashCode 和 equals 方法的有趣面试问题

先决条件: Java中的 Equal 和 Hashcode 方法,为什么要覆盖 equal 和 hashcode 方法

hashCode 和 equals 方法在Java面试中经常被问到。一般来说,我们不会覆盖这两种方法,但是当我们必须覆盖这两种方法时,会有一些场景/要求。当我们将用户定义的对象存储在使用散列算法的 Collection 类中时,就是这样一种情况。即HashTable、HashSet和HashMap。

面试问题:创建一个包含每个员工地址的地图,并使用员工对象作为键。此地图中部分员工的店铺地址。现在创建一个接受 Map 和 Employee 对象作为参数并返回该员工地址的方法。

方法 1(不覆盖 hashCode 和 equals 方法)

// Java program to create a map of employee
// and address Without overriding
// hashCode and equals methods
import java.util.HashMap;
import java.util.Map;
  
class Employee {
private int empId;
private String name;
  
    public Employee(int empId, String name)
    {
        this.empId = empId;
        this.name = name;
    }
  
}
  
class Address {
private int houseNo;
private String streetName;
private String city;
private int pinCode;
  
    public Address(int houseNo, String streetName, 
                         String city, int pinCode)
    {
        this.houseNo = houseNo;
        this.streetName = streetName;
        this.city = city;
        this.pinCode = pinCode;
    }
  
    public String getAddress()
    {
        return houseNo + ", " + streetName +
                   ", " + city + ", " + pinCode;
    }
}
  
public class Test {
    public static String getAddress(Map map, Employee emp)
    {
        Address adrs = (Address)map.get(emp);
        return adrs.getAddress();
    }
    public static void main(String[] args)
    {
  
        Employee emp1 = new Employee(110, "Sajid Ali Khan");
        Address adrs1 = new Address(304, "Marol Mahrisi", 
                                         "Mumbai", 400069);
  
        Employee emp2 = new Employee(111, "Jaspreet Singh");
        Address adrs2 = new Address(203, "Seepz", "Mumbai", 
                                                 400093);
  
        Map map = new HashMap<>();
        map.put(emp1, adrs1);
        map.put(emp2, adrs2);
  
        System.out.println(Test.getAddress(map, new Employee(110, 
                                              "Sajid Ali Khan")));
    }
}

输出:

Exception in thread "main" java.lang.NullPointerException
    at Test.getAddress(Test.java:44)
    at Test.main(Test.java:59)

我们期望输出是员工的地址,但我们得到了 NullPointerException,这很简单。 Map 中的 new Employee(110, “Sajid Ali Khan”) 和参数中的 new Employee(110, “Sajid Ali Khan”) 是两个不同的实例。因此我们得到 NullPointerException因为当我们执行 map.get(emp) 时,它返回 null。

方法 2(覆盖 hashCode 和 equals 方法)

// Java program to create a map of employee
// and address using overriding
// hashCode and equals methods
import java.util.HashMap;
import java.util.Map;
  
class Employee {
private int empId;
private String name;
  
    public Employee(int empId, String name)
    {
        this.empId = empId;
        this.name = name;
    }
  
    @Override public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + empId;
        result = prime * result +
          ((name == null) ? 0 : name.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;
        Employee other = (Employee)obj;
        if (empId != other.empId)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}
  
class Address {
private int houseNo;
private String streetName;
private String city;
private int pinCode;
  
    public Address(int houseNo, String streetName, 
                        String city, int pinCode)
    {
        this.houseNo = houseNo;
        this.streetName = streetName;
        this.city = city;
        this.pinCode = pinCode;
    }
  
    public String getAddress()
    {
        return houseNo + ", " + streetName + ", " + 
                              city + ", " + pinCode;
    }
  
}
  
public class Test {
    public static String getAddress(Map map, Employee emp)
    {
        Address adrs = (Address)map.get(emp);
        return adrs.getAddress();
    }
    public static void main(String[] args)
    {
        Employee emp1 = new Employee(110, "Sajid Ali Khan");
        Address adrs1 = new Address(304, "Marol Mahrisi",
                                       "Mumbai", 400069);
  
        Employee emp2 = new Employee(111, "Jaspreet Singh");
        Address adrs2 = new Address(203, "Seepz", "Mumbai",
                                                  400093);
  
        Map map = new HashMap<>();
        map.put(emp1, adrs1);
        map.put(emp2, adrs2);
  
        System.out.println(Test.getAddress(map, new Employee(110, 
                                              "Sajid Ali Khan")));
    }
}

输出:

304, Marol Mahrisi, Mumbai, 400069

我们得到了预期的输出,这是因为我们在代码中正确地覆盖了 hashCode 和 equals 方法。当我们执行 map.get(emp) 时,它在内部调用我们覆盖的 hashCode 方法,该方法会产生与在 Map 中用作键的员工对象相同的哈希码。

找到正确的存储桶后,将调用 equals 方法并匹配两个 Employee 对象的所有值。结果,我们得到了 Employee 对象的正确地址。