Is it possible to have multiple values for the same key in a hash table? If not, can you suggest any such class or interface which could be used?
In a hashtable, one would use a key/value pair to store information.
In Java, the Hashtable class accepts a single value for a single key. The following is an example of an attempt to associate multiple values to a single key:
Hashtable<String, String> ht = new Hashtable<String, String>();
ht.put("Answer", "42");
ht.put("Hello", "World"); // First value association for "Hello" key.
ht.put("Hello", "Mom"); // Second value association for "Hello" key.
for (Map.Entry<String, String> e : ht.entrySet()) {
System.out.println(e);
}
In an attempt to include multiple values ("World"
, "Mom"
) to a single key ("Hello"
), we end up with the following result for printing the entries in the Hashtable
:
Answer=42
Hello=Mom
The key/value pair of "Hello"
and "World"
is not in the Hashtable
-- only the second "Hello"
and "Mom
" entry is in the Hashtable
. This shows that one cannot have multiple values associate with a single key in a Hashtable
.
What is really needed here is a multimap, which allows an association of multiple values to a single key.
One implementation of the multimap is Multimap from Google Collections:
Multimap<String, String> mm = HashMultimap.create();
mm.put("Answer", "42");
mm.put("Hello", "World");
mm.put("Hello", "Mom");
for (Map.Entry<String, String> e : mm.entries()) {
System.out.println(e);
}
This is similar to the example above which used Hashtable
, but the behavior is quite different -- a Multimap
allows the association of multiple values to a single key. The result of executing the above code is as follows:
Answer=42
Hello=Mom
Hello=World
As can be seen, for the "Hello"
key, the values of "Mom"
and "World"
associated with it. Unlike Hashtable
, it does not discard one of the values and replace it with another. The Multimap
is able to hold on to multiple values for each key.
As others pointed out, no. Instead, consider using a Multimap
which can map many values for the same key.
The Google Collections (update: Guava) library contains one implementation, and is probably your best bet.
Edit: of course you can do as Eric suggests, and store a Collection as a value in your Hashtable (or Map, more generally), but that means writing unnecessary boilerplate code yourself. When using a library like Google Collections, it would take care of the low-level "plumbing" for you. Check out this nice example of how your code would be simplified by using Multimap instead of vanilla Java Collections classes.
What you're looking for is a Multimap. The google collections api provides a nice implementation of this and much else that's worth learning to use. Highly recommended!
Apart from the Google Collections there is a apache Commons Collection object for MultiMap
No. That's kind of the idea of hash tables.
However, you could either roll your own with a Map<YourKeyObject, List<YourValueObject>>
and some utility methods for creating the list if it's not present, or use something like the Multimap from Google Collections.
String key = "hello";
Multimap<String, Integer> myMap = HashMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // prints either "[1, 5000]" or "[5000, 1]"
myMap = ArrayListMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // always prints "[1, 5000]"
Note that Multimap
is not an exact equivalent of the home-baked solution; Hashtable synchronizes all its methods, while Multimap
makes no such guarantee. This means that using a Multimap
may cause you problems if you are using it on multiple threads. If your map is used only on one thread, it will make no difference (and you should have been using HashMap instead of Hashtable
anyway).
See the Google Collections Library for multimaps and similar such collections. The built-in collections don't have direct support for this.