东坑网站建设,可以做水印的网站,青岛网页建站模板,商品网站建设实验格式目录equals方法hashCode方法为什么要一起重写#xff1f;总结面试如何回答重写 equals 时为什么一定要重写 hashCode#xff1f;要想了解这个问题的根本原因#xff0c;我们还得先从这两个方法开始说起。 以下是关于hashcode的一些规定#xff1a;
两个对象相等#xff0…
目录equals方法hashCode方法为什么要一起重写总结面试如何回答重写 equals 时为什么一定要重写 hashCode要想了解这个问题的根本原因我们还得先从这两个方法开始说起。 以下是关于hashcode的一些规定
两个对象相等hashcode一定相等两个对象不等hashcode不一定不等hashcode相等两个对象不一定相等hashcode不等两个对象一定不等
equals方法
Object类默认的equals比较规则就是比较两个对象的内存地址 equals 方法的实现源码如下 通过以下示例就可以说明这个问题
public class Test1 {public static void main(String[] args) {People people1 new People(lisi, 14);People people2 new People(lisi, 14);System.out.println(people1.equals(people2));}
}
class People{private String name;private Integer age;public People(String name, Integer age) {this.name name;this.age age;}
}以上程序的执行结果如下图所示 因此通常情况下我们要判断两个对象是否相等一定要重写 equals 方法这就是为什么要重写 equals 方法的原因。
hashCode方法
Object 的 hashcode 方法是本地方法也就是用 c 或 c 实现的该方法直接返回对象的内存地址让后再转换整数。 hashCode 在 Object 中的源码如下 相等的值 hashCode 一定相同的示例
public class Test1 {public static void main(String[] args) {String s1 abc;String s2 abc;System.out.println(s1 hashCode: s1.hashCode());System.out.println(s2 hashCode: s2.hashCode());}
}以上程序的执行结果如下图所示 不同的值 hashCode 也有可能相同的示例
public class Test1 {public static void main(String[] args) {String s1 Aa;String s2 BB;System.out.println(s1 hashCode: s1.hashCode());System.out.println(s2 hashCode: s2.hashCode());}
}以上程序的执行结果如下图所示
为什么要一起重写
为了解释这个问题我们需要从下面的这个例子入手。 Set 正常使用 Set 集合是用来保存不同对象的相同的对象就会被 Set 合并最终留下一份独一无二的数据。 它的正常用法如下
public class Test1 {public static void main(String[] args) {SetString set new HashSet();set.add(lisi);set.add(lisi);set.add(zhangsan);set.add(zhangsan);System.out.println(Set 集合长度: set.size());// 打印 Set 中的所有元素set.forEach(System.out::println);}
}以上程序的执行结果如下图所示 从上述结果可以看出重复的数据已经被 Set 集合“合并”了这也是 Set 集合最大的特点去重。 Set 集合的异常 如果我们在 Set 集合中存储的是只重写了 equals 方法的自定义对象时有趣的事情就发生了
public class Test1 {public static void main(String[] args) {SetPeople set new HashSet();set.add(new People(lisi, 14));set.add(new People(lisi, 14));System.out.println(Set 集合长度: set.size());// 打印 Set 中的所有元素set.forEach(System.out::println);}
}
class People{private String name;private Integer age;public People(String name, Integer age) {this.name name;this.age age;}Overridepublic String toString() {return People{ name name \ , age age };}Overridepublic boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;People people (People) o;return Objects.equals(name, people.name) Objects.equals(age, people.age);}
}以上程序的执行结果如下图所示 从上述代码和上述图片可以看出即使两个对象是相等的Set 集合竟然没有将二者进行去重与合并。这就是重写了 equals 方法但没有重写 hashCode 方法的问题所在。 解决异常 为了解决上面的问题我们尝试在重写 equals 方法时把 hashCode 方法也一起重写了实现代码如下
public class Test1 {public static void main(String[] args) {SetPeople set new HashSet();set.add(new People(lisi, 14));set.add(new People(lisi, 14));System.out.println(Set 集合长度: set.size());// 打印 Set 中的所有元素set.forEach(System.out::println);}
}
class People{private String name;private Integer age;public People(String name, Integer age) {this.name name;this.age age;}Overridepublic String toString() {return People{ name name \ , age age };}Overridepublic boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;People people (People) o;return Objects.equals(name, people.name) Objects.equals(age, people.age);}Overridepublic int hashCode() {return Objects.hash(name, age);}
} 原因分析 出现以上问题的原因是如果只重写了 equals 方法那么默认情况下Set 进行去重操作时会先判断两个对象的 hashCode 是否相同此时因为没有重写 hashCode 方法所以会直接执行 Object 中的 hashCode 方法而 Object 中的 hashCode 方法对比的是两个不同引用地址的对象所以结果是 false那么 equals 方法就不用执行了直接返回的结果就是 false两个对象不是相等的于是就在 Set 集合中插入了两个相同的对象。 但是如果在重写 equals 方法时也重写了 hashCode 方法那么在执行判断时会去执行重写的 hashCode 方法此时对比的是两个对象的所有属性的 hashCode 是否相同于是调用 hashCode 返回的结果就是 true再去调用 equals 方法发现两个对象确实是相等的于是就返回 true 了因此 Set 集合就不会存储两个一模一样的数据了于是整个程序的执行就正常了。
总结
hashCode 和 equals 两个方法是用来协同判断两个对象是否相等的采用这种方式的原因是可以提高程序插入和查询的速度如果在重写 equals 时不重写 hashCode就会导致在某些场景下例如将两个相等的自定义对象存储在 Set 集合时就会出现程序执行的异常为了保证程序的正常执行所以我们就需要在重写 equals 时也一并重写 hashCode 方法才行。
面试如何回答
1.两个对象的Hashcode值相等但是两个对象的内容值不一定相等—Hash冲突的问题 2.两个对象的值Equals比较相等的情况下则两个对象的Hashcode值一定相等 Hashmap底层中equals和hash值进行比较是否重复和Set集合 在讲一下阿里java手册 注意:String 已覆写 hashCode 和 equals 方法所以我们可以愉快地使用 String 对象作为 key 来使用。