关于 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 对象的正确地址。