[英]HashMap (Open Addressing) Implementation VERY slow
出于某种原因,我使用开放寻址的 HashMap 实现在大型数据集上运行非常缓慢,但我无法弄清楚原因。 谁能提供一些见解? 我只是一名数据结构学生,试图弄清楚为什么我的数据结构如此低效。
我在较小的数据集上运行它,它在我期望的时间内运行,但一旦我启动它,它就失败了。
import java.util.ArrayList;
import java.util.List;
import java.lang.Math;
import java.util.Collections;
import java.lang.reflect.Array;
/**
* @author Cameron Berger
* HASHMap if a data structure which is suppose to be faster than an AVL tree
* for set() and get(), however, I was unsucessful in this. But it works!
*/
public class HASHMap<K extends Comparable<K>,V> implements Map<K,V>{
private class Node{
public K k;
public V val;
public Node(K key, V value) {
k = key;
val = value;
}
}
//time to implement
private List<Node> arr;
private int numKeys;
private int size;
private double loadFactor = 0.5;
/**
* Constructor for HASHMap
**/
public HASHMap(){
size = 16;
arr = new ArrayList<Node>(Collections.nCopies(size, null));
numKeys = 0;
}
public V get(K key){
int index = Math.abs(key.hashCode())%size;
Node n;
for(int i=index; ; i=(i+1)%size){
n = arr.get(i);
if (n == null)
return null;
else if(key.compareTo(n.k)==0)
return n.val;
}
}
public void set(K key, V value){
int index = Math.abs(key.hashCode())%size;
Node n;
for(int i=index; ; i=(i+1)%size){
n = arr.get(i);
if (n == null){
Node temp = new Node(key, value);
arr.set(i, temp);
numKeys++;
break;
}
}
if(Double.compare((numKeys/size),loadFactor)>0){
this.reinitialize();
}
}
/**
* reinitialize reinitializes the HashMap if the loadFactor condition is met
* or there is too much spill over
**/
private void reinitialize(){
int nsize = size*2;
List<Node> nArr = new ArrayList<Node>(Collections.nCopies(nsize, null));
Node temp;
for(int i=0; i<size; i++){
temp = arr.get(i);
if(temp!=null){
K key = temp.k;
int index = Math.abs(key.hashCode())%nsize;
for(int j=index; ; j=(j+1)%nsize){
Node n = nArr.get(j);
if(n==null){
nArr.set(j, temp);
break;
}
}
}
}
this.size = nsize;
this.arr = nArr;
}
public int size(){ return numKeys; }
public List<K> keys(){
List<K> keylist = new ArrayList<K>();
for(int i=0; i<size; i++){
Node n = arr.get(i);
if(n!=null)
keylist.add(n.k);
}
return keylist;
}
public List<V> values(){
List<V> valuelist = new ArrayList<V>();
for(int i=0; i<size; i++){
Node n = arr.get(i);
if(n!=null)
valuelist.add(n.val);
}
return valuelist;
}
}
看起来这部分有问题:
if(Double.compare((numKeys/size),loadFactor)>0){
this.reinitialize();
}
由于numKeys
和size
都是整数,所以这是整数除法——即向下舍入。 因此,当numKeys
和size
相等时,除法的结果只会大于loadFactor
,这实际上意味着您的类的行为就像一个加载因子为 1 而不是 0.5 的哈希表。 这会导致您的开放寻址方案恶化到 O(n) 复杂度而不是 O(1)。
解决方案是更改此条件,以便正确进行比较。 首先,当你除以整数时要小心,但你希望答案是双精度数; 你需要在除法之前加倍。 其次,当可以使用<
或>
时,不要使用Double.compare
。 固定版本如下所示:
if((double) numKeys / size > loadFactor) {
this.reinitialize();
}
或者,为了完全避免除法,您可以等效地测试是否numKeys > loadFactor * size
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.