27

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.

3
  • Aren't you having that Map inside a generic class? Commented Aug 9, 2013 at 22:48
  • Not necessarily. Just looking to create a Map anywhere that just enforces "The keys must be of the same type as the values (or have the same generic type within them, in the case of Key<X>/Value<X>), but each key/value pair can be of a different type." Commented Aug 9, 2013 at 22:54
  • This is exactly what you searched: stackoverflow.com/questions/416540/… Commented Nov 5, 2020 at 9:58

2 Answers 2

28

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Does it make any difference whether I cast the return value to (Value) or (Value<T>) ?
@LucasKuhlemann None whatsoever. Runtime checking of generics bounds isn't possible. Either version doesn't check it (therefore generates a warning), and just assumes you know what you are doing. One via the route of 'oh hey you are using raw types so no type safety', the other via 'oh hey you are casting with generics in the type, which does not do anything, so no type safety'.
0

Use GenericMap custom class and another generic class GenericKey for the key, you can see complete example in this answer

Java map with values limited by key's type parameter

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.