Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / June 2006

Tip: Looking for answers? Try searching our database.

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

Thread view: 
feju2000@gmx.de - 17 Jun 2006 17:08 GMT
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[i]).hashCode();
        }*/
        //String hash = name.hashCode()+""+new Integer(timeShift).hashCode();
        int result = 0;
        for(int i = 0; i<name.length; i++){
            result+=name[i].hashCode();
            result+=new Integer(timeShift[i]).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
Chris Smith - 17 Jun 2006 18:28 GMT
> 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,

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

feju2000@gmx.de - 17 Jun 2006 22:53 GMT
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:

> Hope that helps,
>
> --
> Chris Smith - Lead Software Developer / Technical Trainer
> MindIQ Corporation
Patricia Shanahan - 18 Jun 2006 06:29 GMT
> 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
Chris Smith - 18 Jun 2006 06:45 GMT
> 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.

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

Twisted - 18 Jun 2006 16:30 GMT
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;
Chris Smith - 18 Jun 2006 17:08 GMT
> The equals() method given has another bug -- it's prone to throwing
> ClassCastExceptions, which you may not want. Prepending the following
[quoted text clipped - 3 lines]
> if (this == o) return true;
> if (!(o instanceof NameTimeshift)) return false;

Good catch!

Signature

Chris Smith - Lead Software Developer / Technical Trainer
MindIQ Corporation

feju2000@gmx.de - 19 Jun 2006 14:15 GMT
Okay,
I'll fix both mentioned problems!

Thanks again...

Felix

Chris Smith schrieb:

> > The equals() method given has another bug -- it's prone to throwing
> > ClassCastExceptions, which you may not want. Prepending the following
[quoted text clipped - 9 lines]
> Chris Smith - Lead Software Developer / Technical Trainer
> MindIQ Corporation
Twisted - 19 Jun 2006 20:08 GMT
> > The equals() method given has another bug -- it's prone to throwing
> > ClassCastExceptions, which you may not want. Prepending the following
[quoted text clipped - 5 lines]
>
> Good catch!

Nah, just standard practise in writing equals() methods in my neck of
the woods. :)


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.