对象作为没有Hashcode和equals的Map键

时间:2011-07-29 10:43:24

标签: java

public class Contact
{
    int i;
    String name;
    public Contact(int iVal, String nameVal)
    {
        i = iVal;
        name = nameVal;
    }
}   

public class MultiMap
{
    public static void main (String args[])
    {
        java.util.HashMap m = new java.util.HashMap();
                Contact m1 = new Contact(1, "name");
        Contact m2 = new Contact(1, "name");
        m.put(m1, "first");
        m.put(m2, "second");
        System.out.println(m.get(m1));
        System.out.println(m.get(m2));
    }
}   

输出是:

first 
second 

这种“获取”方法的表现如何?由于m1和M2具有相同的值并且我没有覆盖hashcode(),所以会调用Object类的equals()方法吗?

这是对的吗?

  1. 没有哈希码方法,因此JVM无法查看对象m1和m2是否包含不同的值
  2. 没有重写的equals方法,因此调用了Object类的equals(),并且由于两个对象都不同,上面的代码工作正常,而m2不替换m1的值。

7 个答案:

答案 0 :(得分:11)

当你的类没有覆盖hashCode()equals(Object o)方法时,Java只使用对内存中对象的实际引用来计算值(即检查它是否是相同的实例化)班级)。这就是为什么你仍然得到两个结果。

答案 1 :(得分:3)

所有对象都有hashCode()和equals()。如果未覆盖它们,则使用默认实现。默认行为是将所有对象视为不同,除非它们是同一个对象。

为了进行比较,即使你已经覆盖了hashCode和equals,IdentityHashMap也会这样做。

答案 2 :(得分:2)

它将使用对象类的equals和hashcode方法来查找值(因为Contact不会覆盖equals和hashcode方法),所以是的。

  1. 是的,Java将始终看到两个Contact对象是不同的,因为当它使用对象中的equals方法时将使用对象引用进行比较
  2. 是的,因为必须引用两个联系人对象。

答案 3 :(得分:0)

Contact课程中,您没有实施hashcode()equals()功能。

当HashMap调用这些方法时,它将在父类中搜索这些方法,在这种情况下是Object。

在这种情况下,将评估堆上的对象位置而不是值。

e.g。对于两个对象o1o2

o1.equals(o2) == true仅在o1 == o2

hashCode()是Object类的方法。散列码是JVM对象的整数表示。散列码是系统生成的,JVM将对象的地址作为基础(种子)来生成散列码。生成的散列码在不同的执行时间内不必相同。

答案 4 :(得分:0)

是的,这是正确的。任何没有定义自己的equals和hashcode方法的java对象都会继承java.lang.Object上的默认equals和hascode方法。这些默认实现基于对象引用相等,而不是逻辑上相等。由于您使用相同的对象引用调用了get,因此可以从地图返回该对象。

这是一个进一步说明这一点的例子。

java.util.HashMap m = new java.util.HashMap();
Contact m1 = new Contact(1, "name");
Contact m2 = new Contact(1, "name");
m.put(m1, "first");
m.put(m2, "second");
System.out.println(m.get(m1));//first 
System.out.println(m.get(m2));//second
System.out.println(m.get(new Contact(1, "name"));//null - since the new object has a different object reference.

答案 5 :(得分:0)

虽然m1和m2具有相同的值,但它们是不同的对象引用。

这是正确的: 没有哈希码方法,因此JVM无法查看对象m1和m2是否包含不同的值 - >所以它使用Object类的hasCode()方法来计算hashCode值来执行get(),它返回不同的哈希值(显而易见)。

第二点也是正确的: 由于您还没有实现自己的equals(),因此只有当一个对象与自身进行比较时,才会考虑Object的equals(),它返回 true

答案 6 :(得分:0)

默认情况下,Object类覆盖hashCode和equals方法。这就是您获得所需输出的原因。

如果不重写equals和hashcode方法,JVM会在场景后面检查它。由于m1和m2都是不同的对象实例,因此equals方法始终返回false。 即:

<强> 1。等于:

m1.equals(m2)//返回false,因为两者都是不同的实例。

<强> 2。对于hashCode: //请参阅HashMap.java中的源代码

HashMap内部用于在放入hashMap之前重新发送密钥。见下文。

[![Source code of put method][1]][1]
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

对于rehash,hashMap有自己的静态哈希方法:

[![Source code of hash method][1]][1] 
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

在内部,equals和hashCode方法都以这种方式工作,这就是为什么你得到存储在HashMap中的两个值。

希望这会有所帮助:)