1

Based on the following code snippet :

  Hashtable balance = new Hashtable();
  Enumeration names;
  String str;
  double bal;

  balance.put("Zara", new Double(3434.34)); //first entry for Zara
  balance.put("Mahnaz", new Double(123.22));
  balance.put("Zara", new Double(1378.00)); //second entry for Zara
  balance.put("Daisy", new Double(99.22));
  balance.put("Qadir", new Double(-19.08));

  System.out.println(balance.entrySet());

.

Output : [Qadir=-19.08, Mahnaz=123.22, Daisy=99.22, Zara=1378.0]
  1. Why isn't chaining happening here? When I re-enter with Zara as key the old value is overwritten. I expected it to be added at the end of the Linked List at Zara".hashcode() index.
  2. Does Java use separate chaining only for collision handling?
  3. If I can't use chaining( as I'v tried above) please suggest a common method to do so.
Dubby
  • 1,154
  • 3
  • 16
  • 31

2 Answers2

4

Does Java use separate chaining only for collision handling?

Yes. You can only have one entry per key in a Hashtable (or HashMap, which is what you should probably be using - along with generics). It's a key/value map, not a key/multiple-values map. In the context of a hash table, the term "collision" is usually used for the situation where two unequal keys have the same hash code. They still need to be treated as different keys, so the implementation has to cope with that. That's not the situation you're in.

It sounds like you might want a multi-map, such as one of the ones in Guava. You can then ask a multimap for all values associated with a particular key.

EDIT: If you want to build your own sort of multimap, you'd have something like:

// Warning: completely untested
public final class Multimap<K, V> {
    private final Map<K, List<V>> map = new HashMap<>();

    public void add(K key, V value) {
        List<V> list = map.get(key);
        if (list == null) {
            list = new ArrayList();
            map.put(key, list);
        }
        list.add(value);
    }

    public Iterable<V> getValues(K key) {
        List<V> list = map.get(key);
        return list == null ? Collections.<V>emptyList()
                            : Collections.unmodifiableList(list);
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Then how does the collision handling happen? If the same key is hashed again I lose the previous data! – Dubby Jun 22 '14 at 08:16
  • @Dubby: Yes, as documented. "Collisions" in hashtables are to do with two unequal keys having the same hash code, whereas you've simply got the same key... at which point the previous entry is replaced, as documented. – Jon Skeet Jun 22 '14 at 08:17
  • Could you point out how I could not lose data in terms of code? I understand the theory but am still at loss about how to go about implementing it – Dubby Jun 23 '14 at 11:26
  • @Dubby: Well either you'd create your own map which has a list of values, or you'd use something like `Multimap` from Guava. It's not clear what you've tried or what your goal is. – Jon Skeet Jun 23 '14 at 11:35
  • What I'm trying to do is that if I add a new salary for an employee (in my example Zara) then it should store all the previous salaries as well as a list and not overwrite them like it's happening write now. – Dubby Jun 23 '14 at 11:42
  • @Dubby: Right, so you want a `HashMap>` (except you should probably use `BigDecimal` for a salary, not `Double`) – Jon Skeet Jun 23 '14 at 11:44
  • Could you give a sample line of code showing how to add a value to this type of HashMap? I'm unable to add to the List here :| – Dubby Jun 23 '14 at 11:52
  • @Dubby: I've edited my answer to give an example. But it's really just to get you started - if you have more questions, you should ask in a new question. I consider your original qusetion to be answered now. – Jon Skeet Jun 23 '14 at 11:56
3

Quote from the documentation of Map (which Hashtable is an implementation of):

An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.

(emphasis mine)

The documentation of put() also says:

If the map previously contained a mapping for the key, the old value is replaced by the specified value

So if you want multiple values associated with a key, use a Map<String, List<Double>> instead of a Map<String, Double>. Guava also has a Multimap, which does what you want without having to deal with Lists explicitely as with a Map<String, List<Double>>.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255