繁体   English   中英

Java中的hashcode()和equals()的工作?

[英]Working of hashcode() and equals() in java?

这是我们将用于放入hasmap的类。 它已经覆盖了equals()hashcode()方法。

class Dog
    {
        public String name;
        public Dog(String n)
        {
            name=n;
        }
        @Override
        public int hashCode() {
            System.out.println("in hashcode");
            return name.length();
        }
        @Override
        public boolean equals(Object obj) {
            System.out.println("in equals");
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Dog other = (Dog) obj;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }


    }

此代码主要

Map<Object,Object> m=new HashMap<Object,Object>();
        Dog d1=new Dog("clover");
        m.put(d1,"Dog Key");
        System.out.println(m.get(d1));

产生

in hashcode
in hashcode
Dog Key

但是下面的代码

Map<Object,Object> m=new HashMap<Object,Object>();
        Dog d1=new Dog("clover");
        m.put(d1,"Dog Key");
        System.out.println(m.get(new Dog("clover")));

产生

in hashcode
in hashcode
in equals
Dog Key

如您所见,第二个输出中有一个对equals()方法的调用。 为什么会这样?
我的第二个问题
如果更改键Map的名称属性,则m = new HashMap();

Dog d1=new Dog("clover");
        m.put(d1,"Dog Key");

        d1.name="arthur";
        System.out.println(m.get(new Dog("clover")));

o / p是

in hashcode
in hashcode
in equals
null

即使我更改了键值,但我仍在尝试通过提供相同的键来检索该值。 那为什么要检索null呢?

对于第一个问题: HashMap需要调用equals()来确认两个具有相同哈希码的Dog对象实际上是相等的。 它不需要第一次调用equals() ,因为它使用==来检查使用与先前指定的对象完全相同的特殊情况。

对于第二个问题:您更改了一个数据成员,该成员更改了哈希码的计算以及equals()的结果。 这特别违反了规则,因此地图已损坏; 在那时,任何事情都可能发生。 切勿将具有可变数据的对象用作HashMap键!

这是因为在将d1=new Dog("clover") d1.name="arthur"; ,您将其名称更改为d1.name="arthur"; 因此,名称为arthur Dog不再等于new Dog("clover")

因此,首先首先检查密钥哈希码,然后将其匹配为"clover".length等于"arthur".length ,这可以标识保存对象的存储桶。 之后,执行equals()检查以从存储桶中获取正确的对象,但此操作失败,因为您的密钥不等于所提供的密钥。

实际上,使用可变字段进行哈希码计算不是一个好习惯。

让我们考虑一下HashMap的工作原理。

  1. 许多对象可以具有相同的hashCode。 当您将对象放入地图时,它会根据hashCode方法的结果构建表。 HashMap将具有相同hashCode的对象存储在列表中,并且每个此类列表都通过与特定hashCode关联的单元格附加到表。
  2. 从地图上获取对象时,它会评估传递的键对象的hashCode,然后获取与给定hashCode相关联的对象列表。 然后使用equals方法在列表中找到对象。

对HashMap使用适当的哈希码算法和容量设置,通常可以达到O(1)性能。

现在让我们考虑您的问题:

  1. 你去放,然后从hashMap获取。 您会看到“等于”语句,因为您有不同的键对象。 当键相同时,需要进行一些优化,在这种情况下,HasMap不会调用equals方法。 在第一种情况下,d1 == d1,但是第二种情况下d1!= new Dog(“ clover”)。
  2. 您的对象具有相同的hashCode,但不再相等。 和键不同

但是,如果您在其中更改代码:

Dog d1=new Dog("clover");
    m.put(d1,"Dog Key");

    d1.name="arthur";
    System.out.println(m.get(d1));

最后应该给你带来麻烦。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM