hashcode()和equals()方法
先说结论:重写hashcode()方法后一定要重写equals()方法;重写equals()方法也一定要重写hashcode()方法。
hashcode()和equals()方法的关系:
首先,这两个方法都是java.lang.Object类下的方法;
/** * native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。 */ public native int hashCode() /** * 用于比较 2 个对象的内存地址是否相等,String 类对该方法进行了重写以用于比较字符串的值是否相等。 */ public boolean equals(Object obj)
hashcode()方法是通过对象的物理内存地址值进行一定运算后得到的int值;
equals()方法是直接比较对象的值,若为基本数据类型,则比较值;若为引用类型,则比较其存储的地址值;
而重写equals()方法通常是为了比较类的各项属性相同时(如Person的姓名和年龄),判定二者为相同的,即equals()方法得到true;
而重写hashcode()方法通常是为了相同属性的值在hash后定位同一位置,如若不然,按原有的hashcode()方法,相同属性的两个对象极大概率不在同一位置,那么加入hashset后明显不符合集合定义(对象的唯一性);
equals()方法重写的思路:先判断二者的地址是否一样,若一样,则为同一对象,必然相同;再判断是否是相同类或其子类,如果不是那直接判false;再依据具体的属性值(如姓名年龄/长宽高等)是否相同;
@Override public boolean equals(Object obj) { if (this == obj) return true; // 同一引用 if (obj == null || getClass() != obj.getClass()) return false; // 空或者类型不同 Person person = (Person) obj; // 强制转换 return age == person.age && Objects.equals(name, person.name); // 比较字段 }
hashcode()方法重写的思路:利用对象中所有的属性进行一定运算;
@Override public int hashCode() { int result = 17; // 任意一个非零常数 result = 31 * result + name.hashCode(); // 字符串类型调用自身hashCode方法 result = 31 * result + age; // 基本类型直接使用值 return result; }
思考这个问题时的思路:先分析两个方法重写前后的逻辑,再谨记hashset不能存放相同元素的时候去思考这两者的关系。