哈希的小混乱

时间:2014-09-10 13:41:55

标签: java hash collections equals hashcode

请考虑以下代码:

public class CarEqualsTestAgain {

String model;

    public CarEqualsTestAgain(String x) {
        this.model=x;
    }

    @Override
    public int hashCode(){               //bad hashcode
        System.out.println("__hash__");
        return 1;
    }

    @Override
    public boolean equals(Object o){
        System.out.println("In equals");
        if((o instanceof CarEqualsTestAgain) && ((CarEqualsTestAgain)o).model==this.model){
            return true;
        }
        else
            return false;
    }

    public static void main(String[] args) {

        Map map=new HashMap();

        CarEqualsTestAgain car1=new CarEqualsTestAgain("8");
        map.put(car1, "Red");
        System.out.println("Key1 : "+map.get(car1));         //Line 1

        CarEqualsTestAgain car2=new CarEqualsTestAgain("8");
        System.out.println("Key2 : "+map.get(car2));         //Line 2

        CarEqualsTestAgain car3=car1;
        System.out.println("Key3 : "+map.get(car3));         //Line 3

        CarEqualsTestAgain car4=new CarEqualsTestAgain("9");
        map.put(car4, "Red");
        System.out.println("Key4 : "+map.get(car4));         //Line 4

        CarEqualsTestAgain car5=new CarEqualsTestAgain("10");
        map.put(car5, "Red");
        System.out.println("Key5 : "+map.get(car5));          //Line 5

        CarEqualsTestAgain car6=new CarEqualsTestAgain("8");
        map.put(car6, "Green");
        System.out.println("Key6 : "+map.get(car6));          //Line 6

        key=(String)map.get(car1);
        System.out.println("Key1 : "+key);                    //Line 7

    }

}

将输出打印为:

__hash__
__hash__
Key1 : Red

__hash__
In equals
Key2 : Red

__hash__
Key3 : Red

__hash__
In equals
__hash__
Key4 : Red

__hash__
In equals
In equals
__hash__
Key5 : Red

__hash__
In equals
In equals
In equals
__hash__
In equals
In equals
In equals
Key6 : Red

__hash__
In equals
In equals
Key1 : Green

我的问题是:

1)当创建每个Object时,JVM计算其哈希码并将其放入存储桶中或当调用Hashmap put()方法时,只有JVM使用关键Object来计算哈希码?

2)put()和get()调用hashcode和equals方法。因此put()方法调用正确地覆盖了equals(),具体取决于no。铲斗中的物体,如第1,4,5,6行的输出所示。但是对于get()方法,它是不一样的。对于第1行,get()不调用equal(),第2行没有,第3,4,5行没有调用,第6行没有调用。第7行没有为什么?

3)equals(Object o)方法比较传递的对象,即对象o,所有对象都驻留在桶中,并带有给定的哈希码。那么为什么它不能在早期找到它时停止共同制作。 Ex - 在桶1928中说car1 car4 car5驻留,所以当car6调用get()时调用equals()然后如果car6与car1比较并且发现它相等那么它应该停止比较,而是比较3次。为什么?

1 个答案:

答案 0 :(得分:1)

  

当创建每个Object时,JVM计算其哈希码并将其放入存储桶中或当调用Hashmap put()方法时,只有JVM使用关键Object来计算哈希码?

只有在需要时才会调用hashCode() - 在这种情况下,当您致电put()get()时。

  

对于第1行,get()不会调用equal(),第2行没有,第3,4,5行没有调用,第6行没有调用。第7行没有为什么?

您对自己的诊断感到困惑。这个电话:

System.out.println("Key1 : "+map.get(car1)); 

相当于:

Object tmp = map.get(car1);
System.out.println("Key1 : " + tmp);

因此,在打印equals之前,对Key1的调用会发生。为了使其更易于理解,您应该将诊断更改为:

System.out.println("Test 1");
CarEqualsTestAgain car1 = new CarEqualsTestAgain("8");
System.out.println("Created car");
map.put(car1, "Red");    
System.out.println("Added car to map");
Object tmp = map.get(car1);
System.out.println("Result of get: " + tmp);

这样就更清楚了。通常,put()get()都需要:

  • 在您添加/提取
  • 的密钥上拨打hashCode()
  • 如果该哈希码与地图中的现有哈希码匹配,请为每个匹配调用equals(),直到它用完匹配或找到相同的对象
  

3)equals(Object o)方法比较传递的对象,即对象o,所有对象都驻留在桶中,并带有给定的哈希码。那么为什么它在早期发现一个时就不会停止comapring。 Ex - 在桶1928中说car1 car4 car5驻留,所以当car6调用get()时调用equals()然后如果car6与car1比较并且发现它相等那么它应该停止比较,而是比较3次。为什么?

您首先假设它与car1进行比较。哈希映射实际上是无序的 - 不能保证哪些具有相同哈希码的候选者将被比较。当在找到匹配时停止。如果您将哈希码更改为更合理,则很可能只需要检查一个项目。