Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
内部HashMap工作:如何在java中实现hashCode_Java_Hashmap_Hashcode - Fatal编程技术网

内部HashMap工作:如何在java中实现hashCode

内部HashMap工作:如何在java中实现hashCode,java,hashmap,hashcode,Java,Hashmap,Hashcode,我正在努力为下面给出的学生类编写合适的hashCode函数 1) 我认为hashCode应该足够好,这样两个不同对象的hashCode就不会相互冲突 观察:对于这个实现,当我调试并检查“HashMap的内部表对象”类时,我发现HashMap中的每个条目都被分配了不同的bucket位置 问题:在每个索引处都有一个bucket(列表/树)的目的是什么 实施: @Override public int hashCode() { final int prime = 31; int res

我正在努力为下面给出的学生类编写合适的hashCode函数

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

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

问题:在每个索引处都有一个bucket(列表/树)的目的是什么

实施:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + id;
    return result;
}
@Override
public int hashCode() {
    return id%20;
}
2) 如果我允许哈希代码冲突:

观察:对于这个实现,当我调试和检查时,发现“hashMap内部表的大小”不断增加,并且只使用hashCode范围内的bucket。Rest所有bucket索引都显示null

问:如果hashCode范围之外的bucket始终为空,那么增加内部表大小的目的是什么

实施:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + id;
    return result;
}
@Override
public int hashCode() {
    return id%20;
}
需要适当的hashCode实现帮助,以便解决上述问题。 提前谢谢你的帮助

=====================================代码===========================

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;
}

}
公共类HashMapTest{
公共静态void main(字符串a[]{
HashMap set=新的HashMap();
对于(int i=0;i<5000;i++){
设置.放置(新学生(i),i);
}
集合。放置(新生(5001),5001);
System.out.println(set.size());
}
}
班级学生{
私有int-id;
公立学生(国际id){
this.id=id;
}
//在此处添加注释中提供的hashCode()。
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(getClass()!=obj.getClass())
返回false;
学生其他=(学生)obj;
if(id!=其他.id)
返回false;
返回true;
}
}
在每个索引处都有一个bucket(列表/树)的目的是什么

HashMap不要求hashCode是唯一的,因为这通常无法实现(例如,有2^32个hashcodes,但无限多的
字符串
,因此不可能对每个
字符串使用不同的hashCode)。相反,它只要求碰撞很少

因此,HashMap的实现使得即使发生冲突,它仍能正常工作(尽管在这种情况下它可能工作得更慢)。这就是HashMap使用桶的原因,如果需要,桶可以存储多个元素

如果hashCode范围之外的bucket始终为null,那么增加内部表大小的目的是什么

HashMap会调整表的大小,因为这样做会拆分存储桶。通常,拆分一个存储桶会导致某些元素进入其中一个存储桶,而另一个存储桶中的某些元素会提高性能。它没有意识到您的哈希代码是如此糟糕,以至于所有元素都将保留在同一个bucket中,所以一直在尝试:-)

需要适当的hashCode实现帮助,以便解决上述问题

我会用

@Override
public int hashCode() {
    return id;
}
如果id是唯一的(它的名字似乎暗示了这一点),那么这是一个完美的哈希函数,而且它的计算速度更快:-)


(请注意,
hashCode
可能大于表的大小;
HashMap
将根据需要截断它来处理此问题)

假设学生由
id
唯一标识,只需直接使用
id
作为哈希代码即可。没必要弄坏它。如果您想了解更多关于
HashMap
internal的信息,web上有许多文章描述了HashMap是如何工作的,例如,请参阅Wikipedia关于(相同的东西,不同的名称)。>“如果我允许hashCode冲突”。通常,无论哈希函数是什么,哈希代码冲突都是不可避免的。Java中的哈希代码是一个int,因此允许大约2^32个不同的值。生成2^32+1个不同的Java对象(例如Longs)非常简单,因此至少可以保证一次冲突。话虽如此,您确实希望尽可能降低碰撞的可能性,@Andreas的建议非常有意义。还应该提到,
.hashCode()
.equals(Object)
应该始终成对实现。因为在识别正确的bucket之后,使用
.equals(Object)
方法来查找匹配的对象另请参见此答案:由于OP正确地实现了
equals
,因此我觉得没有必要提及这一点,但是
equal
对象必须具有相等的
hashCodes
。感谢您的回答。。。完全消除了所有的疑虑。