• 使用对象作为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键的对象成功。

        

  • 相关阅读:
    java基础5 (一维)数组和二维数组
    Java 内部类
    Java 抽象类和接口
    Java 多态
    Java 继承
    Java 包(package)
    Java String类和StringBuffer类
    Java 数组
    Java 封装与类
    Java 概述和编程基础
  • 原文地址:https://www.cnblogs.com/liyafei/p/8052145.html
Copyright © 2020-2023  润新知