重写equals()方法时,需要同时重写hashCode()方法
- package com.wangzhu.map;
- import java.util.HashMap;
- /**
- * hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,<br/>
- * 这样的散列集合包括HashSet、HashMap以及HashTable。<br/>
- * 能否可以直接根据hashCode值判断两个对象是否相等呢?<br/>
- * 答案:肯定是不可以的,因为不同的对象可能会生成相同的hashCode值。<br/>
- * 虽然不能根据hashCode值判断两个对象是否相等,但是可以直接根据hashCode值判断两个对象不等,<br/>
- * 如果两个对象的hashCode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,则必须通过equals方法。<br/>
- * 也就是说对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashCode值必定相等。<br/>
- * 如果equals方法得到的结果为,则两个对象的hashCode值不一定不同; <br/>
- * 如果两个对象的hashCode值不等,则equals方法得到的结果必为;<br/>
- * 如果两个对象的hashCode值相等,则equals方法得到的结果未知。<br/>
- *
- * @author wangzhu
- * @date 2015-2-1下午11:22:42
- *
- */
- public class DemoMap2 {
- /**
- * @param args
- */
- public static void main(String[] args) {
- Student stu = new Student(21, "John");
- HashMap<Student, Integer> map = new HashMap<Student, Integer>();
- map.put(stu, 1);
- System.out.println(map.get(stu));//
- System.out.println(map.get(new Student(21, "John")));//
- /**
- * 若Student只重写equals方法而没有没有重写hashCode方法时,则输出为null
- */
- stu.setAge(22);
- System.out.println(map.get(stu));// null
- /**
- * 在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,<br/>
- * 那么对这同一个对象调用多次, hashCode方法必须始终如一地返回同一个整数。<br/>
- *
- * 设计hashCode()时最终稿的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值。<br/>
- * 如果在将一个对象用put()添加进HashMap时产生一个hashCode值,而用get()取出时却产生另一个hashCode值,<br/>
- * 那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,<br/>
- * 因为此数据变化时,hashCode() 方法就会生成一个不同的散列码。<br/>
- */
- }
- }
- class Student {
- int age;
- String name;
- public Student(int age, String name) {
- super();
- this.age = age;
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = (prime * result) + age;
- result = (prime * result) + ((name == null) ? 0 : name.hashCode());
- return result;
- }
- /**
- * 重写时,需要让equals方法与hashCode方法始终在逻辑上保持一致性。
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (this.getClass() != obj.getClass()) {
- return false;
- }
- Student other = (Student) obj;
- if (age != other.age) {
- return false;
- }
- if (name == null) {
- if (other.name != null) {
- return false;
- }
- } else if (!name.equals(other.name)) {
- return false;
- }
- return true;
- }
- }
下面是HashMap中的put方法【JDK1.6】
- public V put(K key, V value) {
- if (key == null)
- return putForNullKey(value);
- int hash = hash(key.hashCode());
- int i = indexFor(hash, table.length);
- for (Entry<K,V> e = table[i]; e != null; e = e.next) {
- Object k;
- if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
- V oldValue = e.value;
- e.value = value;
- e.recordAccess(this);
- return oldValue;
- }
- }
- modCount++;
- addEntry(hash, key, value, i);
- return null;
- }
备注:put方法是用来向HashMap中添加新的元素。从put方法的具体实现可知,其会先调用hashCode方法得到该元素的hashCode值【经过处理的】,然后查看其是否存在于table数组中,如果存在则调用equals方法来确定是否是存在该元素;如果存在,则更新value值,否则将新的元素添加到HashMap中。
下面是HashMap中的get方法【JDK1.6】
- public V get(Object key) {
- if (key == null)
- return getForNullKey();
- int hash = hash(key.hashCode());
- for (Entry<K,V> e = table[indexFor(hash, table.length)];
- e != null;
- e = e.next) {
- Object k;
- if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
- return e.value;
- }
- return null;
- }
备注:get方法是用来将HashMap中对应Key的值Value取出来。从get方法的具体实现可知,其会先调用hashCode方法得到该元素的hashCode值,然后查看其在table数组中是否存在,如果存在则调用equals方法来确定是Key对应的元素,并返回其Value,否则返回null。
重写equals()方法时,需要同时重写hashCode()方法的更多相关文章
- 第九条:覆盖equals方法时总要覆盖hashCode方法
Object类的hashCode方法: public native int hashCode(); 是一个本地方法. 其中这个方法的主要注释如下: Whenever it is invoked o ...
- 【Java实战】源码解析为什么覆盖equals方法时总要覆盖hashCode方法
1.背景知识 本文代码基于jdk1.8分析,<Java编程思想>中有如下描述: 另外再看下Object.java对hashCode()方法的说明: /** * Returns a hash ...
- 半夜思考, 为什么建议重写 equals() 方法时, 也要重写 hashCode() 方法
我说的半夜, 并不是真正的半夜, 指的是在我一个人的时候, 我会去思考一些奇怪的问题. 要理解 hashCode() 需要理解下面三个点: hash契约 哈希冲突 哈希可变 第一点: hash 契约指 ...
- 覆写equals方法为什么需要覆写hashCode方法
覆写equals方法必须覆写hashCode方法,是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢? void test() { // Person类的实例作为Map的k ...
- 在IE浏览器中执行OpenFlashChart的reload方法时无法刷新的解决方法
由于项目需求,需要在网页上利用图表展示相关数据的统计信息,采用了OpenFlashChart技术.OpenFlashChart是一款开源的以Flash和Javascript为技术基础的免费图表,用它能 ...
- 第八条——覆盖equals方法时需遵守的通用约定
1)自反性 对于任何非null的引用值x,x.equals(x)必须返回true.---这一点基本上不会有啥问题 2)对称性 对于任何非null的引用值x和y,当且仅当x.equals(y)为true ...
- 为什么重写equals时必须重写hashCode方法?
原文地址:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html 首先我们先来看下String类的源码:可以发现Stri ...
- 为什么重写equals时必须重写hashCode方法?(转发+整理)
为什么重写equals时必须重写hashCode方法? 原文地址:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html ...
- Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- why在重写equals时还必须重写hashcode方法
首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法 public boolean equals(Object anO ...
随机推荐
- zedboard搭建交叉编译环境
参考:http://blog.csdn.net/xzyiverson/article/details/11264417 我安装的LINUX12.04LTS 双系统 下载好交叉编译软件xilinx-20 ...
- 第四届蓝桥杯C/C++A组题目:振兴中华
首先把题目贴上来吧! 小明参加了学校的趣味运动会,其中的一个项目是:跳格子. 地上画着一些格子,每个格子里写一个字,如下所示:(也可参见图1) 从我做起振 我做起振兴 做起振兴中 起振兴中华 图1 比 ...
- $.each遍历json对象
查看一个简单的jQuery的例子来遍历一个JavaScript数组对象. var json = [ {"id":"1","tagName": ...
- 1105. Spiral Matrix (25)
This time your job is to fill a sequence of N positive integers into a spiral matrix in non-increasi ...
- .NET Framework 3.5 安装错误:0x800F0906、0x800F081F、0x800F0907
使用Add-WindowsFeature 照成的问题 I get the failure below.. If I pick the Server 2012 R2 image from 8/15/2 ...
- Virtualbox中安装Openwrt
Virtualbox:https://www.virtualbox.org/wiki/DownloadsOpenwrt:http://downloads.openwrt.org/backfire/10 ...
- 关于Oracle表空间数据文件自增长的一些默认选项
昨天,一个同事请教了一些关于Oracle表空间数据文件自增长的问题,解答过程中顺便整理起来,以后其他同事有同样的疑问时可以直接查阅. 实验内容: 创建MYTEST表空间,默认不开启自增长. 给MYTE ...
- matlab实现贝塞尔曲线绘图pdf查看
贝塞尔曲线绘图方法: %Program 3.7 Freehand Draw Program Using Bezier Splines %Click in Matlab figure window to ...
- Cocos2dx中的四种控件及主要用法
1.控件:即控制对象,控制按钮之类的精灵 2.主要介绍四大类控件: CCControlSlider:进度条 CCControlSwitch:开关 CCScale9Sprite:9妹图(用于缩放) CC ...
- android重写view和viewgroup的区别
重写view: View类一般用于绘图操作,重写它的onDraw方法,但它不可以包含其他组件,没有addView(View view)方法. 重写viewgroup: ViewGroup是一个组件容器 ...