本文共 2222 字,大约阅读时间需要 7 分钟。
在面试Java初级开发时,提到自定义类在HashMap中存储时遇到的问题,往往会引发关于equals
和hashCode
方法的讨论。很多候选人表示自己从未重写过这两个方法,这不仅会导致实际开发中遇到问题,还可能在面试中暴露对Java内存管理和集合机制的理解不足。本文将从HashMap的存储规则入手,解释为什么要重写hashCode
和equals
方法,以及它们的重要性。
Hash表(即哈希表)是一种高效的数据结构,能够在平均O(1)时间内完成查找、插入和删除操作。与传统的线性表(如ArrayList)相比,Hash表的平均查找时间从O(n/2)显著降低到O(1)。
Hash表的核心原理是通过将键(Key)和值(Value)映射到一个特定位置(Index),称为Hash值。Java中的HashMap采用了链地址法来解决Hash冲突。
当我们将自定义对象存入HashMap时,如果不重写hashCode
和equals
方法,可能会遇到以下问题:
import java.util.HashMap;class Key { private Integer id; public Key(Integer id) { this.id = id; } // hashCode和equals方法被注释掉}public class WithoutHashCode { public static void main(String[] args) { Key k1 = new Key(1); Key k2 = new Key(1); HashMaphm = new HashMap<>(); hm.put(k1, "Key with id is 1"); System.out.println(hm.get(k2)); }}
问题1:无法通过相同值的对象正确取值
hashCode
方法未重写,k1
和k2
的hashCode
值分别为它们的内存地址。由于k1
和k2
是不同的对象,hashCode
值不同,导致无法通过k2
取到对应的值。问题2:无法正确判断对象相等
equals
方法未重写,k1
和k2
会被视为两个不同的对象,无法找到正确的链表节点。class Key { private Integer id; public Key(Integer id) { this.id = id; } public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } Key key = (Key) o; return Objects.equals(id, key.id); } public int hashCode() { return id != null ? id.hashCode() : 0; }}public class WithoutHashCode { public static void main(String[] args) { Key k1 = new Key(1); Key k2 = new Key(1); HashMaphm = new HashMap<>(); hm.put(k1, "Key with id is 1"); System.out.println(hm.get(k2)); // 输出:"Key with id is 1" }}
效果1:相同值的对象能正确取值
k1
和k2
的hashCode
值相同,存储在同一个链表节点下。效果2:能正确判断对象相等
equals
方法判断对象的id
是否相等,确保k2
能找到k1
的链表节点。在面试中,提到hashCode
和equals
方法时,可以深入探讨以下问题:
你有没有重写过hashCode
方法?
hashCode
方法,确保每个对象的hashCode
与其属性值相关联。你在使用HashMap时有没有重写hashCode
和equals
方法?
你是怎么写的?
hashCode
方法,使用对象的属性值计算哈希码。同时,重写了equals
方法,判断对象的属性是否相等。重写hashCode
和equals
方法的主要作用是确保自定义对象能像预期一样存储和查找。这种做法不仅避免了哈希冲突,还能保证HashMap
正确地找到目标对象。对于开发人员来说,这是基础的OOP知识,熟练掌握它对项目开发和面试中都至关重要。
转载地址:http://fcpc.baihongyu.com/