This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
Hello all. I'm new here and I had nowhere else to go! Hopefully some of you can help me. I have a HashSet that will work at times and won't work at others! Here's the deal:
I have a public class called Developer that has two instance variables:
private String developerName; private static HashSet<Developer> masterCollection = new HashSet<Developer>();
developerName is simply the name of the developer and masterCollection is a set off ALL developers that has ever been created w/o duplicates.
IMPORTANT: I have overridden both the equals and hashcode methods. I have the hashcode method returning the hashcode for the developer's name. My equals method checks to see whether two developer names are spelled exactly the same. I knew that both of those methods should be coded hand in hand.
Now... in a test class I wrote, I would create new Developers with names as parameters as it is mandatory for this function. When I created two or more developers with the same exact name, the test class would detect that it was already in the set. That's all fine and good.
BUT!!! I also have a method called rename(String name) that simply renames the name of the developer. Nothing more, nothing less. This is where the trouble comes in.
When I do a print out of what is in the set, the change in name shows up correctly in place of what it was called before, but when I create a new Developer object with the name of a Developer object I just renamed, there ends up being TWO of those objects in the set! It ends up going through! This only happens with renamed objects! Even when I see that their hashcodes are the same! Also of mention, I just happen to run a contains() method, using the set, on the Developer object I just renamed and it returns FALSE, even though a print of the set says otherwise. If it's false that the object is not in the set, then why when I print the set, does the new name of the developer show up???
Why is this happening?? Do you think that because my hashcode() method searches for the Developer's name, the set works incorrectly when renamed? This is really stalling progress as I need this to push forward with the rest of the program. Your help is GREATLY appreciated! Thanks in advance. I will frequent back in order to respond to any questions you may have for me. [ February 18, 2007: Message edited by: Bear Bibeault ]
Imagine you are a librarian in an odd sort of library. You keep books in alphabetical order. There's an "A" shelf, a "B" shelf, a "C" shelf... and a "Z" shelf.
The odd part is that the books in your library are printed with that newfangled e-ink, the kind that can be changed electronically.
So the first day, you get a shipment with 100 books. You sort them in alphabetical order and put each one on the right shelf. There's about 4 books on each shelf. One book is the 1907 children's title, "Mumford Monkey's Mom is Missing". Not surprisingly, you file this on the "M" shelf.
While you sleep, the publisher decides that since no-one has actually read Mumford in 70 years, all the existing copies should be re-programmed to be copies of the wildly popular new children's book, "Albert Alligator's Apple Adventure". They accomplish this by wireless Internet, without bothering you about it.
The next day, someone comes in bright and early and asks for a copy of "Albert". You go to the "A" shelf to look for it. But it ain't there, is it?
It's on the "M" shelf.
You have to turn your customer away, as you can't find a copy.
Later you get another shipment of book, including a copy of "Albert", which you file on the "A" shelf. Then you do the nightly inventory, and, surprise! You find that you have two copies of "Albert," one where it belongs, and one out of place.
OK, now. Hopefully you understand the parallel to your current situation. The objects used as keys in a HashSet or HashMap can't just change their hashcodes while they're in the set/map, or the data structures of the set/map are immediately corrupted. The proper way to do things is to remove the object from the collection, change the hashcode (i.e., the name) and then put it back in the collection. You could embed this logic in the setName() method, if you'd like, or provide a st.atic "rename()" method and provide no other way to change the name.