使用对象作为hashMap的键,需要覆盖hashcode和equals方法
1:HashMap可以存放键值对,如果要以对象(自己创建的类等)作为键,实际上是以对象的散列值(以hashCode方法计算得到)作为键。hashCode计算的hash值默认是对象的地址值。
这样就会忽略对象的内容,不是以对象的内容来判断。如果要以对象的内容进行判断,就要覆盖掉对象原有的hashCode方法。
另外HashMap是以equals方法判断当前的键是否与表中存在的键是否相同,所以覆盖hashCode方法之后,还不能正常运行。还要覆盖equals方法
先判断hash(hash函数)值是否相同,相同了说明某个位置上有多个元素,再用equals(线性查找)方法判断。
来看下面一个天气预报系统的例子:
2:创建一个作为HashMap的键的对象Groundhog(土拔鼠)与Prediction(预报)对象联系起来,
package chapter17.nine;
public class Groundhog {
    protected int number;
    public Groundhog(int n) {
        // TODO Auto-generated constructor stub
        number=n;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "Groundhog #"+number;
    }
}
package chapter17.nine;
import java.util.Random;
public class Prediction {
    private static Random random=new Random();  //传递进参数,创建的随机数将会相同
    private boolean shadow=random.nextDouble()>0.5;
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        if(shadow){
            return "Six more weeks of Winter!";
        }else{
            return "Early Spring";
        }
    }
}
3:创建一个测试类
public class SpringDetector {
    public static <T extends Groundhog> void detectSpring(Class<T> type) throws Exception, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        Constructor<T> ghog=type.getConstructor(int.class);  //含有int参数的构造函数
        Map<Groundhog, Prediction> map=new HashMap<Groundhog, Prediction>();
        for (int i = 0; i < 10; i++) {
            map.put(ghog.newInstance(i), new Prediction());
        }
        System.out.println("map="+map);
        Groundhog gh=ghog.newInstance(3);
        System.out.println("Looking up prediction for "+gh);
        if(map.containsKey(gh)){  //map是根据对象生成的hascode地址判断对象是否相同的,
            //如果想让对象作为map的键,来判断对象是否相同。那么对象应该覆盖hashcode和equals方法。生成对象自己的hashcode吗。
            //例如按照对象包含的int属性生成hashcode 吗等。HashMap使用equals判断当前的键是否与表中存在的键相同。所以要覆盖equals方法
            System.out.println(map.get(gh));
        }else{
            System.out.println("Key not found"+gh);
        }
    }
    public static void main(String[] args) {
        try {
            detectSpring(Groundhog.class);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
测试结果:
map={Groundhog #1=Six more weeks of Winter!, Groundhog #4=Six more weeks of Winter!, Groundhog #5=Six more weeks of Winter!, Groundhog #3=Early Spring, Groundhog #8=Six more weeks of Winter!, Groundhog #7=Six more weeks of Winter!, Groundhog #0=Early Spring, Groundhog #2=Early Spring, Groundhog #9=Six more weeks of Winter!, Groundhog #6=Early Spring}
Looking up prediction for Groundhog #3
Key not foundGroundhog #3
我们发现,map中并不包含Groundhog gh=ghog.newInstance(3);的键,可是实际上map中又添加了ghog.newInstance(3)的键。这是为什么呢?
因为实际上判断的对象的hash值。所有造成:第一个ghog.newInstance(3)的hash值不等于第二个ghog.newInstance(3)的hash值;
4:重写Groundhog并覆盖hashCode方法和equals方法
package chapter17.nine;
public class Groundhog2 extends Groundhog{
    public Groundhog2(int n) {
        super(n);
        // TODO Auto-generated constructor stub
    }
    @Override
    public int hashCode() {
        // TODO Auto-generated method stub
        return number;
    }
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return obj instanceof Groundhog2 && number==((Groundhog2)obj).number;
    }
}
5:测试。
package chapter17.nine;
import java.lang.reflect.InvocationTargetException;
public class SpringDetector2 {
    public static void main(String[] args) {
        try {
            SpringDetector.detectSpring(Groundhog2.class);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
6:测试结果。
map={Groundhog #0=Six more weeks of Winter!, Groundhog #1=Early Spring, Groundhog #2=Early Spring, Groundhog #3=Early Spring, Groundhog #4=Early Spring, Groundhog #5=Six more weeks of Winter!, Groundhog #6=Early Spring, Groundhog #7=Early Spring, Groundhog #8=Early Spring, Groundhog #9=Six more weeks of Winter!}
Looking up prediction for Groundhog #3
Early Spring
第一个ghog.newInstance(3)的hash值等于第二个ghog.newInstance(3)的hash值。定义作为HashMap键的对象成功。
使用对象作为hashMap的键,需要覆盖hashcode和equals方法的更多相关文章
- 何时覆盖hashCode()和equals()方法
		
The theory (for the language lawyers and the mathematically inclined): equals() (javadoc) must defin ...
 - 当我们用自定义的类对象作为key时,我们必须在程序中覆盖HashCode()和equals()。
		
Key值既然可以作为对象,那么也可以用一个自定义的类.比如: m.put(new sutdent(“Liucy”,30),”boss”) 如果没有语句来判定Student类对象是否相同,则会全部打印出 ...
 - HashMap中使用自定义类作为Key时,为何要重写HashCode和Equals方法
		
之前一直不是很理解为什么要重写HashCode和Equals方法,才只能作为键值存储在HashMap中.通过下文,可以一探究竟. 首先,如果我们直接用以下的Person类作为键,存入HashMap中, ...
 - 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。
		
我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...
 - (转)为什么要重写 hashcode 和 equals 方法?
		
作者丨hsm_computer cnblogs.com/JavaArchitect/p/10474448.html 我在面试Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候 ...
 - 为什么要重写hashcode和equals方法
		
我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...
 - 重写hashcode和equals方法
		
重写hashcode和equals方法 简乐君 2019-05-07 21:55:43 35481 收藏 191分类专栏: Java 文章标签: equals() hashcode()版权 一.前言我 ...
 - JAVA中的各种 哈希码(HashCode) 与 equals方法在HIBERNATE的实际应用[转载]
		
1.什么是哈希码(HashCode) 在Java中,哈希码代表对象的特征.例如对象 Java代码 String str1 = “aa”, str1.hashCode= 3104 String str2 ...
 - K:java中的hashCode和equals方法
		
hashCode和equals方法是Object类的相关方法,而所有的类都是直接或间接的继承于Object类而存在的,为此,所有的类中都存在着hashCode和equals.通过翻看Object类 ...
 
随机推荐
- 【gitlab】创建ssh 秘钥
			
1).首先打开linux服务器,输入命令:ls -al ~/.ssh,检查是否显示有id_rsa.pub或者id_dsa.pub存在,如果存在请直接跳至第3步. 2).在bash中输入,注意这个地方的 ...
 - 【css系列】创建网页加载进度条
			
一.最简单或者明显的方式是使用定时器 1.在网页中加入布局覆盖真实网页内容 2.使用定时器确定加载所用时间的长短,其实并不是真正的加载进度实现 <!DOCTYPE html> <ht ...
 - 【前端安全】JavaScript防http劫持与XSS (转)
			
作为前端,一直以来都知道HTTP劫持与XSS跨站脚本(Cross-site scripting).CSRF跨站请求伪造(Cross-site request forgery).但是一直都没有深入研究过 ...
 - 原生js--http请求
			
1.终止请求和超时 终止请求XMLHttpRequest对象提供abort方法,调用该方法时触发abort事件 XHR2提供了timeout属性,当超时发生时触发timeout事件.但浏览器尚不支持自 ...
 - OGG日常运维监控的自动化脚本模板
			
#!/usr/bin/ksh export ORACLE_BASE=/oracle/ export ORACLE_SID=epmln1 export ORACLE_HOSTNAME=pmlnpdb1 ...
 - reserve和resize区别
			
reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素.加入新的元素时,要调用push_back()/insert()函数. resize是改变容 ...
 - 数组和字符串的基础题目学习(EPI)
			
学习的速度有些慢,脑袋转动的频率有些不是很高.不过今天的效率我觉得还是可以,应该不能称效率吧,就是整个感觉不错,感觉自己补充了很多的知识.其实G家和F家败了之后不知道看看算法题对接下来的找工作帮助是否 ...
 - 阻止form表单提交的问题
			
阻止form表单提交这种场景可能在生活中,我们经常碰到,而在我们第一印象里面可能我们用return false 去阻止表单默认行为. 但是,有中情况我们用return false 不能阻止表单提交 & ...
 - msyql DATETIME类型和Timestamp之间的转换
			
DATETIME -> Timestamp: UNIX_TIMESTAMP(...) Timestamp -> DATETIME: FROM_UNIXTIME(...) select da ...
 - Django之forms
			
Django forms 关于select和checkbox设置初始选中值 Django的forms和models一样很牛逼.他有两种功能,一是生成form表单,还有就是form表单的验证. 这里主要 ...