• Java用自定义的类型作为HashMap的key


      需要重写hashCode()和equals()方法才可以实现自定义键在HashMap中的查找。

    public class PhoneNumber
    {
        private int prefix; //区号
        private int phoneNumber; //电话号
    
        public PhoneNumber(int prefix, int phoneNumber)
        {
            this.prefix = prefix;
            this.phoneNumber = phoneNumber;
        }
    }
    
    import java.util.HashMap;
    
    public class Test1
    {
        public static void main(String[] args)
        {
            HashMap<PhoneNumber, String> map = new HashMap<>();
    
            map.put(new PhoneNumber(027, 12345678), "zhangsan");
            map.put(new PhoneNumber(027, 22222222), "lisi");
            map.put(new PhoneNumber(027, 33333333), "wangwu");
            map.put(new PhoneNumber(027, 33333333), "abc");
    
            System.out.println(map.toString());
    
            System.out.println(map.get(new PhoneNumber(027, 12345678)));
            System.out.println(map.get(new PhoneNumber(027, 22222222)));
            System.out.println(map.get(new PhoneNumber(027, 33333333)));
        }
    }
    

    运行结果为:

    {package1.PhoneNumber@74a14482=zhangsan, package1.PhoneNumber@677327b6=wangwu, package1.PhoneNumber@1540e19d=lisi, package1.PhoneNumber@14ae5a5=abc}
    null
    null
    null

    从中我们可以看到出现了两个问题:

    • new PhoneNumber(027, 33333333)这个键被添加了两次,但是在HashMap中wangwu和abc同时存在了
    • 使用get方法取得的值均为null

    正确的方法就是直接对PhoneNumber类进行修改,覆盖equals和hashCode方法,修改后的PhoneNumber类如下:

    public class PhoneNumber
    {
        private int prefix; //区号
        private int phoneNumber; //电话号
    
        public PhoneNumber(int prefix, int phoneNumber)
        {
            this.prefix = prefix;
            this.phoneNumber = phoneNumber;
        }
    
        @Override
        public boolean equals(Object o)
        {
            if(this == o)
            {
                return true;
            }
            if(!(o instanceof PhoneNumber))
            {
                return false;
            }
            PhoneNumber pn = (PhoneNumber)o;
            return pn.prefix == prefix && pn.phoneNumber == phoneNumber;
        }
    
        @Override
        public int hashCode()
        {
            int result = 17;
            result = 31 * result + prefix;
            result = 31 * result + phoneNumber;
            return result;
        }
    }
    

    重新执行上述函数,结果为:

    {package1.PhoneNumber@1fce2ef=abc, package1.PhoneNumber@bca3e8=zhangsan, package1.PhoneNumber@1535828=lisi}
    zhangsan
    lisi
    abc

    可以看到,之前出的错误都被改正了

    在HashMap中,查找key的比较顺序为:

    1. 计算对象的HashCode,看在表中是否存在
    2. 检查HashCode位置中的对象是否与当前对象相等

    以上使用计算HashCode的方法在effective java第九点中提到:

    • 对于对象中每个关键域f,为该域计算int类型的散列码c,result = 31 * result + c
  • 相关阅读:
    P4068 [SDOI2016]数字配对
    牛客挑战赛43 集合操作
    codefoces 1393D Rarity and New Dress
    codefoces 1400E Clear the Multiset
    [TJOI2017]城市 树形dp
    codefoces 1407E Egor in the Republic of Dagestan
    codefoces 1407D Discrete Centrifugal Jumps
    java保留两位小数(四舍五入和非四舍五入)
    JAVA在命令行进行输入输出重定向(JAVA SentinelValue)
    分治法(排列问题)
  • 原文地址:https://www.cnblogs.com/liuyang0/p/6271343.html
Copyright © 2020-2023  润新知