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方法的更多相关文章

  1. 何时覆盖hashCode()和equals()方法

    The theory (for the language lawyers and the mathematically inclined): equals() (javadoc) must defin ...

  2. 当我们用自定义的类对象作为key时,我们必须在程序中覆盖HashCode()和equals()。

    Key值既然可以作为对象,那么也可以用一个自定义的类.比如: m.put(new sutdent(“Liucy”,30),”boss”) 如果没有语句来判定Student类对象是否相同,则会全部打印出 ...

  3. HashMap中使用自定义类作为Key时,为何要重写HashCode和Equals方法

    之前一直不是很理解为什么要重写HashCode和Equals方法,才只能作为键值存储在HashMap中.通过下文,可以一探究竟. 首先,如果我们直接用以下的Person类作为键,存入HashMap中, ...

  4. 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

  5. (转)为什么要重写 hashcode 和 equals 方法?

    作者丨hsm_computer cnblogs.com/JavaArchitect/p/10474448.html 我在面试Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候 ...

  6. 为什么要重写hashcode和equals方法

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

  7. 重写hashcode和equals方法

    重写hashcode和equals方法 简乐君 2019-05-07 21:55:43 35481 收藏 191分类专栏: Java 文章标签: equals() hashcode()版权 一.前言我 ...

  8. JAVA中的各种 哈希码(HashCode) 与 equals方法在HIBERNATE的实际应用[转载]

    1.什么是哈希码(HashCode) 在Java中,哈希码代表对象的特征.例如对象 Java代码 String str1 = “aa”, str1.hashCode= 3104 String str2 ...

  9. K:java中的hashCode和equals方法

      hashCode和equals方法是Object类的相关方法,而所有的类都是直接或间接的继承于Object类而存在的,为此,所有的类中都存在着hashCode和equals.通过翻看Object类 ...

随机推荐

  1. Matlab练习——寻找完全数

    clc; clear; wq = []; : sum = ; k = ; : i / sum = sum + j; end end == i wq=[wq i]; end end disp(['2至1 ...

  2. Delphi应用程序的调试(三)监视变量

    监视变量(Watching Variables) 当程序停在一个断点处时,用户做些什么呢?通常用户在断点处停下来是要检查变量的值,某个变量的值是否与预料的取值相同?或者某个变量取什么值(事先并不知道这 ...

  3. 【大数据系列】win10上安装hadoop开发环境

    为了方便采用了Cygwin模拟linux环境的方法 一.安装JDK以及下载hadoop hadoop官网下载hadoop http://hadoop.apache.org/releases.html  ...

  4. [原]secureCRT 改变显示宽度

    1.首先全局设置:Options - Global Options - Terminal - Appearance - Maximumcolumns 最大只能设置成1024(推荐256),设置越大越占 ...

  5. myisam与innodb索引比较

    MyISAM支持全文索引(FULLTEXT).压缩索引,InnoDB不支持 InnoDB支持事务,MyISAM不支持 MyISAM顺序储存数据,索引叶子节点保存对应数据行地址,辅助索引很主键索引相差无 ...

  6. [转] 基于TINY4412的Andorid开发-------简单的LED灯控制

    阅读目录 一.编写驱动程序 二.编写代码测试驱动程序 三.编写HAL代码 四.编写Framework代码 五.编写JNI代码 六.编写App 参考资料: <Andriod系统源代码情景分析> ...

  7. 微信公众号关联(小游戏 小程序 跳转 盒子 wx.navigateToMiniProgram)

    参考: 公众号关联小程序 关联公众号 关联后,登录小游戏,可在设置-关联设置中看到关联的公众号 在小游戏中使用wx.navigateToMiniProgram wx.navigateToMiniPro ...

  8. 微信小游戏 50M那部分的缓存机制的使用

    一.使用 AssetsManager 灵活定制微信小游戏的缓存策略 官网教程:http://developer.egret.com/cn/github/egret-docs/Engine2D/mini ...

  9. Linux下openoffice与SWFtools的安装

    第一部份:OpenOffice的安装 1.Openoffice的官网:http://www.openoffice.org/download/index.html 选择Linux 64-bit(x860 ...

  10. javap(反汇编命令)详解

    javap是JDK自带的反汇编器,可以查看java编译器为我们生成的字节码.通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作. 语法: javap [ 命令选项 ] class. . ...