内部HashMap工作:如何在java

时间:2016-08-06 18:03:36

标签: java hashmap hashcode

我正在努力为下面给出的Student类编写正确的hashCode函数。

1)我认为hashCode应该足够好,以便两个不同对象的hashCode不会相互冲突。

观察:对于这个实现,当我调试并检查“HashMap的内部表对象”类时,我发现HashMap中的每个条目都分配了不同的存储桶位置。

问题:在每个索引处有一个存储桶(列表/树)的目的是什么。

实施:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + id;
    return result;
}

2)如果我允许hashCode的碰撞:

观察:对于这个实现,当我调试和检查时,发现'hashMap的内部表的大小'不断增加,并且只使用了hashCode范围内的桶。休息所有存储桶索引显示为空。

问题:如果hashCode范围内的桶总是为空,则增加内部表大小的目的是什么。

实施:

@Override
public int hashCode() {
    return id%20;
}

需要有关正确hashCode实现的帮助,以便可以修复上述问题。 感谢您的帮助。

============================ Code ================== =========

public class HashMapTest {

public static void main(String a[]) {
    HashMap<Student, Integer> set = new HashMap<Student, Integer>();

    for (int i = 0; i < 5000; i++) {
        set.put(new Student(i), i);
    }

    set.put(new Student(5001), 5001);
    System.out.println(set.size());
}
}

class Student {
private int id;

public Student(int id) {
    this.id = id;
}

// Add here hashCode() provided in comments.


@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Student other = (Student) obj;
    if (id != other.id)
        return false;
    return true;
}

}

1 个答案:

答案 0 :(得分:2)

  

在每个索引处使用存储桶(列表/树)的目的是什么。

HashMap不要求hashCode是唯一的,因为这通常无法实现(例如,有2 ^ 32个哈希码,但是无限多Strings,所以不可能使用不同的hashCode每String}。相反,它只要求碰撞罕见

因此,实现HashMap使得即使存在冲突它仍然可以正常工作(尽管在这种情况下它可能工作得更慢)。这就是为什么HashMap使用可以在必要时存储多个元素的存储桶。

  

如果hashCode范围内的存储区始终为null,则增加内部表大小的目的是什么。

HashMap调整表的大小,因为这样做会拆分桶。通常,拆分存储桶会导致一些元素进入一个,而另一个存储区中的某些元素会提高性能。它没有意识到你的hashCode是如此糟糕,所有元素将保留在同一个桶中,所以继续尝试: - )

  

需要有关正确hashCode实现的帮助,以便可以修复上述问题。

我用

@Override
public int hashCode() {
    return id;
}

如果id是唯一的(其名称似乎暗示),这是一个完美的哈希函数,它甚至可以快速计算: - )

(请注意hashCode可能大于表格大小; HashMap会根据需要截断它来处理这个问题。