3

I have a curious situation - there is a HashMap, that is initialized as follows:

    HashMap<String, HashSet<String>> downloadMap = new HashMap<String, HashSet<String>>();

and then I have the following things, that will be executed indefinitely via a quartz scheduler:

    myHashSet = retrieve(animal);
    downloadMap.put(myKey, myHashSet);
    // do stuff
    downloadMap.get(myKey).clear();

What happens after, is that one value gets associated with the different keys. So, for instance, I will have things like:

 Kitens [cute kitten, sad kitten]
 Puppies [cute kitten, sad kitten]

Which never should happen.

Particularly, after I retrieve the HashSet of the kittens:

 myHashSet = retrieve(animal);

myHashSet = [cute kitten, sad kitten] downloadMap = Kittens [], Puppies[]

then put() is executed and I get:

 downloadMap =  Kitens [cute kitten, sad kitten], Puppies [cute kitten, sad kitten]

Does anyone knows why this is the case?

Thank you in advance!

James Dunn
  • 8,064
  • 13
  • 53
  • 87
user2187935
  • 751
  • 2
  • 8
  • 19
  • What does your `retrieve(animal)` return? Where and how do you set `animal` and where is `myKey` changed? – Java Devil Sep 03 '13 at 03:09
  • retrieve(animal) returns HashSet, based on the parameter animal - could be cat, puppy etc. If it is a cat, the hashset contains values such as [cute kitten, sad kitten], if its a puppy then then [cute puppy, sad puppy] etc. The animal is getting passed via quartz trigger to the job. There are no problem with retriever(animal) though - it returns what it supposed to return. EDIT: I've looked at the other responses and it seems that what it might be the problem with the retrieve(animal), particularly returning a new hashset each time it is called. I'll give it another tomorrow,thank you! – user2187935 Sep 03 '13 at 05:55

2 Answers2

3

Looks like you use the same HashSet<String> reference in all your values of the HashMap<String, HashSet<String>>. Knowing this, the problem is how you insert the HashSet<String>s in your HashMap. Note that you must use a new HashSet<String> reference for every key-value pair.

Update your question accordingly to receive a more specific answer.

Not directly associated to the real problem, it is better to program oriented to interfaces instead of direct class implementations. With this, I mean that you should declare the downloadMap variable as

Map<String, Set<String>> downloadMap = new HashMap<String, Set<String>>();

Similar for the Sets that will be put in this map.

More info:

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
1

The solution is to re-program retrieve() so it returns a different HashSet every time it is called. In fact, my preferred solution consists in allowing the caller to specify where to retrieve objects as a parameter:

    myHashSet= retrieve( new HashSet<String>() ) ;

So, if a different program ever wanted to accumulate objects in a single set, it could simply do so by calling retrieve with the same set. The client has the last word!

Mario Rossi
  • 7,651
  • 27
  • 37