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. Oracle —— 如何执行SQL文件

    在Command模式下(笔者使用的是 PL/SQL Comand Window),输入 @文件路径\文件名 如: @D:\ORA_SQL\INSERT_SQL.sql

  2. testmath

    $\Huge ans = \frac{ \sum\limits_{i=1}^{m}{ (x_i - \bar{x})^2 } }{m} \cdot m^2 \\$

  3. Linux下应急工具

    Linux下的应急工具 在Linux下,应急的查看点无非那个几个,一是看表现(宕机.高CPU.高内存.高IO.高网络通信),二看连接.三看进程.四看日志.五看文件(Linux一切皆文件),再者结合起来 ...

  4. Word插入htm文件导致文本域动态增加的一个问题

    受html标签影响,超链接也会被变成文本域(HYPERLINK).当遍历文本域进行替换之前如果预存了文本域的数量(Count/Length/etc.)将导致遗漏.

  5. Docker制作私有的基础镜像

    debootstrap是debian/ubuntu下的一个工具,用来构建一套基本的系统(根文件系统).生成的目录符合Linux文件系统标准(FHS),即包含了/boot./etc./bin./usr等 ...

  6. Css中!important的用法

    !important为开发者提供了一个增加样式权重的方法.应当注意的是!important是对整条样式的声明,包括这个样式的属性和属性值 <!DOCTYPE HTML> <html& ...

  7. 【CF878D】Magic Breeding bitset

    [CF878D]Magic Breeding 题意:有k个物品,每个物品有n项属性值,第i个人的第j个属性值为aij,有q个操作: 1 x y 用x和y合成一个新的物品,新物品的编号是++k,新物品的 ...

  8. [Key] RegCure Pro

    Serial RegCure Pro  : 4A803-C4F23-422B6-1F3D6 http://www.paretologic.com/product/regcure-pro/

  9. dhroid - ioc基础(@Inject*)

    1 ioc即控制反转.控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心.控制反转还有一 ...

  10. android 常见内存泄漏原因及解决办法

    android常见内存泄漏主要有以下几类: 一.Handler 引起的内存泄漏. 在Android开发中,我们经常会使用Handler来控制主线程UI程序的界面变化,使用非常简单方便,但是稍不注意,很 ...