Reputation: 23
I'm trying to resizing my array when N, the number of elements, is greater than m/2, m is the initial size of the array, but it doesn't work and I don't understand why. This array should work like an hashtable, so I have an hashing function before every insert, and after the resizing I want to insert again every element with a new hashing (m value changed). This is the error:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at JumpHashing.resize(JumpHashing.java:55)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
at JumpHashing.hashing(JumpHashing.java:40)
at JumpHashing.resize(JumpHashing.java:61)
at JumpHashing.put(JumpHashing.java:50)
The problem is clearly the resizing, without it (with less than 23 elements) it works.
Inititial size of m is 23, this is the actual code (Class "In" for reading file from algs4):
public class JumpHashing{
private int m;
private int[] hashTable;
private static int id;
private int N;
public JumpHashing(){
m = 23;
hashTable = new int[m];
N = 0;
}
public void hashing(int value) {
int key = (value*11)%m;
put(key, value);
}
public void put(int key, int value) {
if(N <m/2) {
hashTable[key] = value;
N++;
} else {
m=m*2;
N=0;
resize(m);
}
}
public void resize(int m) {
int[] temp = new int[m];
for(int i=0; i<hashTable.length; i++) {
temp[i] = hashTable[i];
}
hashTable = new int[m];
for(int i=0; i<temp.length; i++) {
hashing(temp[i]);
}
}
public static void main(String[] args) {
JumpHashing hashT1 = new JumpHashing();
In file = new In("random.txt");
while(file.hasNextLine()) {
int value = Integer.parseInt(file.readLine());
hashT1.hashing(value);
}
for(int j=0; j<hashT1.hashTable.length; j++) {
StdOut.println("Key: "+j+" Value: "+hashT1.hashTable[j]);
}
}
}
Upvotes: 1
Views: 159
Reputation: 5581
You end up repeatedly calling resize
until memory is used up. The problem is in this function:
public void resize(int m) {
int[] temp = new int[m]; // <-- this is the new double-size of m
for(int i=0; i<hashTable.length; i++) {
temp[i] = hashTable[i];
}
hashTable = new int[m];
for(int i=0; i<temp.length; i++) { // <-- here we go too far
hashing(temp[i]);
}
}
Your second loop goes through the full new 'm' size array, not the original m/2 size array. Half way plus one through the loop your N
will be greater than m/2
again and it will call resize every time that happens.
Here's what you should have in that function:
public void resize(int m) {
int[] oldHash = hashTable;
hashTable = new int[m];
for(int i=0; i<oldHash.length; i++) {
if (oldHash[i] != 0) { // <-- don't hash empty slots
hashing(oldHash[i]);
}
}
}
This also improves performance because you loop through just once and no more than m/2 times.
Upvotes: 1