Is there a way in Java to have a map where the type parameter of a value is tied to the type parameter of a key? What I want to write is something like the following:
public class Foo {     // This declaration won't compile - what should it be?     private static Map<Class<T>, T> defaultValues;      // These two methods are just fine     public static <T> void setDefaultValue(Class<T> clazz, T value) {         defaultValues.put(clazz, value);     }      public static <T> T getDefaultValue(Class<T> clazz) {         return defaultValues.get(clazz);     } }   That is, I can store any default value against a Class object, provided the value's type matches that of the Class object. I don't see why this shouldn't be allowed since I can ensure when setting/getting values that the types are correct.
EDIT: Thanks to cletus for his answer. I don't actually need the type parameters on the map itself since I can ensure consistency in the methods which get/set values, even if it means using some slightly ugly casts.
4.2. First, let's see how to declare the Map and put various types' data in it: Map<String, DynamicTypeValue> theMap = new HashMap<>(); theMap. put("E1 (Integer)", new IntegerTypeValue(intValue)); theMap. put("E2 (IntArray)", new IntArrayTypeValue(intArray)); theMap.
If you call put(K, V) twice, with the same key but different values, the multimap contains mappings from the key to both values. Show activity on this post. I use Map<KeyType, Object[]> for associating multiple values with a key in a Map. This way, I can store multiple values of different types associated with a key.
If this is an application requirement, the three best ways to solve the 'multiple values per key in a map in Java' problem are: Stick with the standard APIs and add a collection class like a 'Vector' or 'ArrayList' to your map or set. Use the MultiMap and MultiValueMap classes from the Apache Commons library.
HashMap can be used to store key-value pairs. But sometimes you may want to store multiple values for the same key. For example: For Key A, you want to store - Apple, Aeroplane.
You're not trying to implement Joshua Bloch's typesafe hetereogeneous container pattern are you? Basically:
public class Favorites { private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>(); public <T> void setFavorite(Class<T> klass, T thing) { favorites.put(klass, thing); } public <T> T getFavorite(Class<T> klass) { return klass.cast(favorites.get(klass)); } public static void main(String[] args) { Favorites f = new Favorites(); f.setFavorite(String.class, "Java"); f.setFavorite(Integer.class, 0xcafebabe); String s = f.getFavorite(String.class); int i = f.getFavorite(Integer.class); } }
From Effective Java (2nd edition) and this presentation.
The question and the answers made me come up with this solution: Type-safe object map. Here is the code. Test case:
import static org.junit.Assert.*;  import java.util.ArrayList; import java.util.List;  import org.junit.Test;   public class TypedMapTest {     private final static TypedMapKey<String> KEY1 = new TypedMapKey<String>( "key1" );     private final static TypedMapKey<List<String>> KEY2 = new TypedMapKey<List<String>>( "key2" );      @Test     public void testGet() throws Exception {          TypedMap map = new TypedMap();         map.set( KEY1, null );         assertNull( map.get( KEY1 ) );          String expected = "Hallo";         map.set( KEY1, expected );         String value = map.get( KEY1 );         assertEquals( expected, value );          map.set( KEY2, null );         assertNull( map.get( KEY2 ) );          List<String> list = new ArrayList<String> ();         map.set( KEY2, list );         List<String> valueList = map.get( KEY2 );         assertEquals( list, valueList );     } }   This is the Key class. Note that the type T is never used in this class! It's purely for the purpose of type casting when reading the value out of the map. The field key only gives the key a name.
public class TypedMapKey<T> {     private String key;      public TypedMapKey( String key ) {         this.key = key;     }      @Override     public int hashCode() {         final int prime = 31;         int result = 1;         result = prime * result + ( ( key == null ) ? 0 : key.hashCode() );         return result;     }      @Override     public boolean equals( Object obj ) {         if( this == obj ) {             return true;         }         if( obj == null ) {             return false;         }         if( getClass() != obj.getClass() ) {             return false;         }         TypedMapKey<?> other = (TypedMapKey<?>) obj;         if( key == null ) {             if( other.key != null ) {                 return false;             }         } else if( !key.equals( other.key ) ) {             return false;         }         return true;     }      @Override     public String toString() {         return key;     } }   TypedMap.java:
import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set;  public class TypedMap implements Map<Object, Object> {     private Map<Object, Object> delegate;      public TypedMap( Map<Object, Object> delegate ) {         this.delegate = delegate;     }      public TypedMap() {         this.delegate = new HashMap<Object, Object>();     }      @SuppressWarnings( "unchecked" )     public <T> T get( TypedMapKey<T> key ) {         return (T) delegate.get( key );     }      @SuppressWarnings( "unchecked" )     public <T> T remove( TypedMapKey<T> key ) {         return (T) delegate.remove( key );     }      public <T> void set( TypedMapKey<T> key, T value ) {         delegate.put( key, value );     }      // --- Only calls to delegates below      public void clear() {         delegate.clear();     }      public boolean containsKey( Object key ) {         return delegate.containsKey( key );     }      public boolean containsValue( Object value ) {         return delegate.containsValue( value );     }      public Set<java.util.Map.Entry<Object, Object>> entrySet() {         return delegate.entrySet();     }      public boolean equals( Object o ) {         return delegate.equals( o );     }      public Object get( Object key ) {         return delegate.get( key );     }      public int hashCode() {         return delegate.hashCode();     }      public boolean isEmpty() {         return delegate.isEmpty();     }      public Set<Object> keySet() {         return delegate.keySet();     }      public Object put( Object key, Object value ) {         return delegate.put( key, value );     }      public void putAll( Map<? extends Object, ? extends Object> m ) {         delegate.putAll( m );     }      public Object remove( Object key ) {         return delegate.remove( key );     }      public int size() {         return delegate.size();     }      public Collection<Object> values() {         return delegate.values();     }  } 
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With