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. 安装ahci驱动后出现A disk read error occurred如何解决

    注意:因为一般的ghost系统盘都没有ahci驱动,所以,如果用到固态硬盘且想更好的发挥固态硬盘的性能,需要安装ahci驱动,且在bios 中把硬盘模式设置成ahci(否则电脑会蓝屏或进不去系统) 步 ...

  2. 【转】VC 隐藏模块、MFC 改变窗口类名

    [转]VC 隐藏模块 void HideDll() { HMODULE hMod = ::GetModuleHandle("MyHook.dll"); PLIST_ENTRY He ...

  3. 【laravel5.6】laravel 自定义公共函数

    1.在 app/Helpers/ 新建一个文件 functions.php,当然这个文件位置和名称你可以自己定义,创建一些函数用于全局调用: 2.在composer.json中的autoload下增加 ...

  4. Delphi XE 10 跨平台三层数据库应用教程

    Delphi XE 10 跨平台三层数据库应用教程 前言: Delphi XE 开始越来越庞大,比经典的Delphi7难用,但依然是目前所有跨平台开发工具中开发效率最高.最容易上手的,其快速设计RAD ...

  5. LeetCode-494. Target Sum(DFS&DP)

    You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symb ...

  6. junit4 详解

    转:http://www.cnblogs.com/eggbucket/archive/2012/02/02/2335697.html JUnit4概述 JUnit4是JUnit框架有史以来的最大改进, ...

  7. About LOCAL_PRIVATE_PLATFORM_APIS in Android.mk

    LOCAL_PRIVATE_PLATFORM_APIS := true设置后,会使用sdk的hide的api來编译 在Android.mk中如果有LOCAL_SDK_VERSION 这个编译配置,就会 ...

  8. [原]openstack-kilo--issue(一) httpd汇总

    /** 系统环境:redhat7.2 repo:163 openstack version : kilo author: lihaibo **/ 问题1:Invalid command 'group= ...

  9. tcp连接的状态变迁以及如何调整tcp连接中处于time_wait的时间

    一.状态变迁图 二.time_wait状态 针对time_wait和close_wait有个简单的描述帮助理解: Due to the way TCP/IP works, connections ca ...

  10. psr-4

    自动加载: <?php function autoload($className) { $className = ltrim($className, '\\'); $fileName = ''; ...