help with generics - extending hashmap

I'm trying to extend the HashMap class to accept multiple values per key. I'd like .put(key,value) to put a single key/value pair. I'd like .get(key) to return a Vector<V> of all the values associated with key, and .get(key, index) to return a single value of type V for that key. I am using Eclipse 3.2 and Java 1.5.

The problem I am having is my .put(K key,V value) method won't compile, I get the error:

Name clash: The method put(K,V) of type OneToManyHashMap<K,V> has the same erasure as put(K,V> of type HashMap<K,V> but does not override it

My code (roughly):

publicclass OneToManyHashMap<K,V>extends HashMap<K, Vector><V>>{

public V get(Object key,int index){return get(key).get(index);}

public V put(K key, V value){ ...}

public V remove(Object key,int index){return get(key)

}

Yes, I know there is an extra > in the code. It's wasn't there when I typed the message and it's not there when I try and edit the message to remove it :(

Message was edited by:

jiggersplat

[1607 byte] By [jiggersplata] at [2007-11-27 10:17:30]
# 1

I don't think subclassing is logically incorrect here. I would claim you are implementing something that has-a Map < K, List < V > >, not is-a ...

BigDaddyLoveHandlesa at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 2

I still get the same compile error with the put method

public class OneToManyHashMap<K,V> implements Map {

private HashMap<K, Vector><V>> map = new HashMap<K,Vector><V>>();

public V get(Object key, int index) { return map.get(key).get(index); }

public V put(K key, V value) { map.get(key).add(value); }

public V remove(Object key, int index) { return map.get(key).remove(index); }

}

jiggersplata at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 3

> public V put(K key, V value) { map.get(key).add(value); }

This method has a non-void return type, yet you have no return statement.

And I'm not convinced that your class should implement Map, but see how it goes...

BigDaddyLoveHandlesa at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 4

yeah, i just omitted the return, regardless that is not the compile error.

this compiles but i don't like it...

public V put(Object key, Object value) { map.get(key).add((V)value); return... }

further more the signature for Map.put in the javadocs is

V put(K key, V value);

Message was edited by:

jiggersplat

jiggersplata at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 5

There's no need to extend or override anything: Map<Foo, List&lt;Bar>> myMap = new HashMap<Foo, List<Bar>>();

Also, to prevent the extra > characters from being added to your posts, use the &lt; entity instead of <. It's one of several long-standing bugs that the admins can't fix because they're too busy adding new features that nobody wants and that don't work anyway.

uncle_alicea at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 6

Yes, but I don't see how that will support the correct behavior for put and get that I am looking for.

jiggersplata at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 7

> yeah, i just omitted the return, regardless that is

> not the compile error.

>

> this compiles but i don't like it...

>

> ...

Well, that's too bad. You have to return something whether you like it or not.

prometheuzza at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 8

thanks for that tip :P

what i meant was i omitted it from the code i posted in the message, not the code i am trying to compile.

anyway, i changed the class definition from

public class MultipleEntryHashMap<K,V> implements Map

to

public class MultipleEntryHashMap<K,V> implements Map<K,V>

jiggersplata at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 9

I don't think it's possible to turn a Map into a MultiMap by simple extension, given their conflicting semantics. Even using the wrapper technique as you did in reply #2, you still have to implement all the methods of Map. So, for instance, you have to provide get() and remove() methods that don't take index arguments. And if you want to use the added methods that do take indices, you'll have to refer to your MultiMap object by its concrete type, so you lose much of the benefit of extending a built-in collection class.

uncle_alicea at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 10

yeah, most of my methods would look like

public foo bar() {

return map.bar();

}

but get and remove don't do quite what you'd expect. i'm having them return the first value that fits that key, which is not exactly the behavior one would expect from something implementing the map interface. i am starting to agree with you that perhaps implementing the map interface is not appropriate.

jiggersplata at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 11

This is what was meant by a "has-a" relation:

public class OneToManyHashMap<K, V extends List<V>> {

public Map<K, List<V>> map;

public OneToManyHashMap() { map = new HashMap<K, List<V>>(); }

public V get(K key, int index) { return map.get(key).get(index); }

public void put(K key, V value) { map.get(key).add(value); }

public void remove(K key, int index) { map.get(key).remove(index); }

}

Needless to say, you will have to perform some checks to handle eventual NPE's.

prometheuzza at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 12

V extends List<V> ?

BigDaddyLoveHandlesa at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 13

> V extends List<V> ?

Woops, that was when I was trying some other generics-stuff. Forgot to remove it.

It should be this:public class OneToManyHashMap<K, V> {

// ...

}

Thanks BigDaddy.

prometheuzza at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...
# 14

> ...

> Needless to say, you will have to perform some checks

> to handle eventual NPE's.

... and create and add a new List when a certain key is not yet present in your map.

prometheuzza at 2007-7-28 15:52:05 > top of Java-index,Java Essentials,Java Programming...