繁体   English   中英

对哈希的困惑不大

[英]Little Confusion Over Hashing

考虑下面的代码:

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)创建每个对象时,JVM计算其哈希码并将其放入存储桶中,或者当调用Hashmap put()方法时,只有JVM使用键Object来计算哈希码?

2)put()和get()调用哈希码和equals方法。 因此,put()方法将根据否正确调用覆盖的equals()。 在第1,4,5,6行的输出中看到存储桶中的对象数量。 但是对于get()方法,它是不一样的。 对于第1行,get()不调用equal(),第2行,第3、4、5行不调用,第6行。 7号线不是为什么?

3)equals(Object o)方法比较传递的对象,即所有对象都驻留在具有给定哈希码的存储桶中的Object o。 那么,为什么它在发现一个早期时就不停止共同映射。 例如-在存储区1928中说car1 car4 car5驻留,因此,当car6调用get()并调用equals()时,如果car6与car1比较并且发现相等,则它应停止比较,但将比较3次。 为什么?

当创建每个对象时,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);

因此, 打印Key1 之前,将调用equals 为了更容易理解,您应该将诊断更改为:

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)方法比较传递的对象,即所有对象都驻留在具有给定哈希码的存储桶中的Object o。 那么,为什么它在发现一个早期时就不停止共同映射。 例如-在存储区1928中说car1 car4 car5驻留,因此,当car6调用get()并调用equals()时,如果car6与car1比较并且发现相等,则它应停止比较,但将比较3次。 为什么?

您假设它首先与car1比较。 哈希映射实际上是无序的-无法保证将比较具有相同哈希码的候选排序。但是,当找到匹配项时, 它将停止。 如果您将哈希码更改为更明智,则很有可能只需要检查一项即可。

暂无
暂无

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

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