Java generics enforce same type for keys and values of map

dictionary, generics, java

Solution

You can do this, but you have to roll your own wrapper on top of a `Map`:

class MyTypeSafeMap {
  private Map<Key<?>, Value<?>> map;
  public <T> void put(Key<T> key, Value<T> value) {
    map.put(key, value); 
  }

  public <T> Value<T> get(Key<T> key) {
    return (Value) map.get(key); 
    // we know it's safe, but the compiler can't prove it
  }
}

Compare e.g. Guava's `ClassToInstanceMap`.

Problem

What I am looking for: I'm looking to construct something that enforces type on both the keys and values of a map: kind of like `Map<Key<X>, Value<X>>`. However, I would additionally like to enforce that types match within each key/value entry, but between entries, no type must should be enforced. For example, within the same map, these key/value pairs should be considered valid: - `Key<Integer>` maps to `Value<Integer>` - `Key<String>` maps to `Value<String>` - `Key<Double>` maps to `Value<Double>` However, something like this would be invalid: - `Key<Integer>` mapping to `Value<String>` - `Key<Double>` mapping to `Value<Boolean>` How can I accomplish this using Java generics? What I'm not looking for: I understand that I can implement something like `Set<Pair>`, where pair accepts Key/Value of the same type. However, looking this up by key would no longer be a constant time operation. I understand that I could do something like `Map<Key<?>, Value<?>>` and just assert that the Key and Value are the same type at runtime. However, I was wondering if this is possible strictly using generics.

Original source

Related problems