Want to show your appreciation? Please to my charity.

Monday, June 19, 2006

Is the definition of Map interface overly restricted in Java 5

I spent entire yesterday evaluating the possibility of Generifying Commons-Collections and still keeps the backward compatibility. It turned out to be not as simple as I thought initially.

Java 5 type-safe Map and Collection strictly requires the data that you retrieve from it must be of the same type of the data you put into it. This becomes a major problem generifying a number of useful Map and Collection implementations in Commons-Collections. For example, MultiMap, TransformedMap. While my initial evaluation goal yet to be archived, what did come to my attention is a difficult question: is the definition of Map (similarly to Collection) interface overly restricted in Java 5?

Well, in the real life, I put an egg in incubator can get the chick back after sometime. So for what reason the get method must return the same type of data as the put(or add or set) method takes? Let's look at the refined Map definition:

public interface Map<K,V,I=V> {
     // Ok, the I=V is something that I made up here, but isn't it neat?
     // It means if I is not given, default to V, assuming our compiler
     // is smart enough to understand it.
     V get(Object o);
     I put(K key, I input);
}

This pseudo Map interface is less restricted so apparently to be much useful. Let's exam how MultiMap can be supported with the refined interface.

public abstract class AbstractHashMap<K,V,I=V> implements Map<K,V,I> {
     public V get(Object object) {
         return ...;
     }
     protected boolean putInternal(K key, V input) {
         // same logic was in put
     }
}
public class HashMap<K,V> extends AbstractHashMap<K,V> {
     public V get(Object object) {
         return ...;
      }
     public V put(K key, V input) {
         return putInternal(key, input)? input:null;
     }
}
public class MultiMap<K,V,I=V> implements Map<K,Collection<V>,I> {
     public Collection<V> get(Object o) {
         return ...;
     }
     public I put(K key, I input) {
     }
}
public abstract class AbstractMultiHashMap<K,V,I=V>
     extends AbstractHashMap<K, Collection<V>, I>
     implements MultiMap<K, V, I>
{
    protected boolean addInternal(K key, V value) {
         Collection<V> c = get(key);
         if(c==null) {
             c= new ArrayList<V>();
             putInternal(key, c);
         }
         c.add(value);
        return true;
     }
}
public class MultiHashMap<K,V> extends AbstractMultiHashMap<K,V> {
    public V put(K key, V input) {
         return addInternal(key, input)? input:null;
     }
}
Obviously, we need to handle setValue in Map.Entry too. This might make it a little complicated but clearly it's doable. EDIT: RFE is filed to Sun and accepted in it's bug databaes

No comments:

Post a Comment