Java 在put方法中重新散列哈希映射
我试图在Java中实现一个单独的链接哈希映射。在put()-方法中,如果加载因子(元素数/数组大小)变大,我想重新散列映射。为此,我编写了另一个方法rehash(),它通过将数组/容量的大小加倍,然后再次添加所有条目(至少我希望它这样做)来重新显示列表。问题是,当我测试它时,我得到了一个“java.lang.OutOfMemoryError:java堆空间”,我猜这是因为我在rehash()方法中调用了put()方法。问题是我真的不知道如何解决这个问题。我想知道是否有人可以检查我的代码,给我反馈或给我一个如何继续的提示。 下面代码中的条目是哈希映射类中的嵌套私有类 提前谢谢 put()方法:Java 在put方法中重新散列哈希映射,java,hashmap,out-of-memory,Java,Hashmap,Out Of Memory,我试图在Java中实现一个单独的链接哈希映射。在put()-方法中,如果加载因子(元素数/数组大小)变大,我想重新散列映射。为此,我编写了另一个方法rehash(),它通过将数组/容量的大小加倍,然后再次添加所有条目(至少我希望它这样做)来重新显示列表。问题是,当我测试它时,我得到了一个“java.lang.OutOfMemoryError:java堆空间”,我猜这是因为我在rehash()方法中调用了put()方法。问题是我真的不知道如何解决这个问题。我想知道是否有人可以检查我的代码,给我反馈
其中size()返回映射中(键、值)对的数量,capacity是数组表(存储链接列表的位置)的大小。您已经添加了
rehash()
,但是仍然缺少load()
实现(或者在load内部,添加size()
)
不过,模式看起来很清晰,允许猜测,等待更多信息
您告诉我们,当荷载系数达到放置
内的某个点时,您将重新进行灰化。这将使内部数组加倍,并再次调用put。最后你没有了记忆
其中,我打赌在你放置的地方会发生一些微妙的或不太微妙的递归,它通过加倍内存使用来重新放置,然后重新放置,这以某种方式创建了一个rehash
ing
第一种可能性是,有一些跟踪数组状态的内部变量未正确重置(例如,占用的条目数…)。将“旧”阵列数据与正在构建的新阵列数据混淆可能是罪魁祸首
另一种可能性是您的
put
实现,但它需要一步一步地调试—我建议您执行调试。一旦您重新刷新映射,一切都将不一样。入口设置的桶等。
所以
- 创建临时表
- 通常使用当前的get方法获取值
- 然后根据重新灰化到新的桶大小创建新的桶,并将新容量添加到表中。(不要使用PUT)
- 然后用刚创建的表替换现有表。确保与新表大小相关的所有值也已更改,例如基于threhholds、capcity等的桶选择方法
最后,使用打印语句跟踪新存储桶和存储桶之间的项目移动。什么是
load()
?抱歉,我编辑了它!是的,但是size()是如何实现的nr_of_keys
?是的,size()只返回nr_of_keys属性!旁注:在我看来,do while()
可以在put中为您节省几行
public V put(K key,V value) {
int idx = key.hashCode()%capacity; //Calculate index based on hash code.
if(idx<0) {
idx+=this.capacity; //if index is less than 0 add the length of the array table
}
if(table[idx]==null) { //If list at idx is empty just add the Entry-node
table[idx] = new Entry<K,V>(key,value);
nr_of_keys +=1;
if(this.load()>=this.load_factor) { //Check if load-factor is greater than maximum load. If this is the case rehash.
rehash();
}
return null;
} else {
Entry<K,V> p = table[idx]; //dummy pointer
while(p.next!=null) { //while next node isn't null move the pointer forward
if(p.getKey().equals(key)) { //if key matches:
if(!p.getValue().equals(value)) { //if value don't match replace the old value.
V oldVal = p.getValue();
p.setValue(value);
return oldVal;
}
} else {
p=p.next;
}
}
if(p.getKey().equals(key)) { //if the key of the last node matches the given key:
if(!p.getValue().equals(value)) {
V oldVal = p.getValue();
p.setValue(value);
return oldVal;
} else {
return null;
}
}
p.next = new Entry<K,V>(key,value); //key doesn't exist so add (key,value) at the end of the list.
nr_of_keys +=1;
if(this.load()>=this.load_factor) { //if load is to large rehash()
rehash();
}
return null;
}
}
public void rehash() {
Entry<K,V>[] tmp = table; //create temporary table
int old_capacity = this.capacity; //store old capacity/length of array.
this.capacity = 2*capacity; //New capacity is twice as large
this.nr_of_keys=0; //reset nr. of keys to zero.
table = (Entry<K, V>[]) new Entry[capacity]; //make this.table twice as large
for(int i=0; i<old_capacity;i++) { //go through the array
Entry<K,V> p = tmp[i]; //points to first element of list at position i.
while(p!=null) {
put(p.getKey(), p.getValue());
p=p.next;
}
}
}
public double load() {
return((double) this.size())/((double)this.capacity);
}