Hashtable filled with own key just has the same keys in enumeration.

F

feju2000

Hi there,
I have a really strange problem:
I fill a Hashtable using an own Object as key:

package trainfile.dictionaries;

public class NameTimeshift {
//private String name="";
String[] name;
int[] timeShift;

public NameTimeshift(String name, int timeShift){
this.name = new String[]{name};
//this.id = id;
this.timeShift = new int[]{timeShift};
}

public NameTimeshift(String[] name, int[] timeShift){
this.name = new String[name.length];
this.name = name;
this.timeShift = new int[timeShift.length];
this.timeShift=timeShift;
}

public int getTimeShift(){
return timeShift[0];
}
public String getName(){
return name[0];
}
public String[] getFollowingName(){
return name;
}
public int[] getFollowingTimeshift(){
return timeShift;
}
public boolean equals(Object o){
NameTimeshift nt = (NameTimeshift)o;
if(nt.hashCode()==this.hashCode()) return true;
return false;
}
public int hashCode(){
/*char[] c = new char[name.toCharArray().length];
c = name.toCharArray();
int result=0;
for(int i = 0; i<c.length; i++){
new Character(c).hashCode();
}*/
//String hash = name.hashCode()+""+new Integer(timeShift).hashCode();
int result = 0;
for(int i = 0; i<name.length; i++){
result+=name.hashCode();
result+=new Integer(timeShift).hashCode();
}
//int hash = name.hashCode()+timeShift.hashCode();
return result;
}
}

The hashcode and equals methods work fine, because filling the
Hashtable works as mentioned.
But after filling the Hashtable and using the Enumeration from the
keys()-method, it seems like the Hashtable just has x-times the last
NameTimeshift-object as keys, where x is the count of Objects I put in
the Hashtable. Why does this problem appear?

Thanks,
Felix
 
C

Chris Smith

I have a really strange problem:
I fill a Hashtable using an own Object as key:

There are actually a couple of problems here. One you've seen, whereas
the other just hasn't happened to bite you yet. First,
public NameTimeshift(String[] name, int[] timeShift){
this.name = new String[name.length];
this.name = name;
this.timeShift = new int[timeShift.length];
this.timeShift=timeShift;
}

This is ultimately the problem. When you use this constructor to create
a new NameTimeshift, it will share the same String[] and int[] that you
passed in. My guess is that you're passing in the same String[] and
int[] to create each object, so your objects are all nominally
different, but they share the same arrays so they look exactly the same.

When you write:
this.name = name;

that discards the previous value of name (which you just assigned) and
replaces it with a pointer to the same object pointed to by the
parameter called name. You probably wanted to copy the contents
instead. That looks like this:

System.arraycopy(name, 0, this.name, 0, name.length);

Do the same for timeShift as well.

The other problem is:
public boolean equals(Object o){
NameTimeshift nt = (NameTimeshift)o;
if(nt.hashCode()==this.hashCode()) return true;
return false;
}

This is a misuse of hashCode. Hash codes are NOT unique between
different objects. They can't be, because a hash code is only 32 bits
long, whereas the number of possible object states in a String is
something like 2^2^16 (about 1 followed by 25000 zeros). The number of
possible states of a String[] and an int[] is far, far greater.

Hash codes provide a first approximation at equality comparison. You
then need to compare the fields themselves to see if they are equal.
That involves using a couple loops to walk through all the elements.

Hope that helps,
 
F

feju2000

Hi Chris,
thank you very much! The equals-method was not the problem or (better
said) did not had to be changed. But the hint to use System.arraycopy
was really useful.

Greetings,
Felix

Chris Smith schrieb:
 
P

Patricia Shanahan

Hi Chris,
thank you very much! The equals-method was not the problem or (better
said) did not had to be changed. But the hint to use System.arraycopy
was really useful.

The equals method issue is a bug, but one that will cause problems
very intermittently, depending on how many items you put in your Hashtable.

Patricia
 
C

Chris Smith

thank you very much! The equals-method was not the problem or (better
said) did not had to be changed. But the hint to use System.arraycopy
was really useful.

As I said before, that's a bug looming in your code that hasn't happened
to bite you yet. It's still wrong, and it will likely cause a
spectacular failure one day unless you fix it. Just because you haven't
seen its effects yet doesn't mean you can safely ignore it.

It's up to you, of course... I just hope you're not writing anything of
importance.
 
T

Twisted

The equals() method given has another bug -- it's prone to throwing
ClassCastExceptions, which you may not want. Prepending the following
two lines to the method body will fix that, as well as speed it up in
certain cases:

if (this == o) return true;
if (!(o instanceof NameTimeshift)) return false;
 
C

Chris Smith

Twisted said:
The equals() method given has another bug -- it's prone to throwing
ClassCastExceptions, which you may not want. Prepending the following
two lines to the method body will fix that, as well as speed it up in
certain cases:

if (this == o) return true;
if (!(o instanceof NameTimeshift)) return false;

Good catch!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top