I don’t think it is possible to do compile-time checks using Java generics. However, it is quite simple at runtime. Just a short decorator on the right:
public class FancyTypeMapDecorator implements Map<Set<? extends Object>, Object> { final Map<Set<? extends Object>, Object> target; public FancyTypeMapDecorator(Map<Set<? extends Object>, Object> target) { this.target = target; } @Override public Object put(Set<? extends Object> key, Object value) { final Class<?> keyElementType = key.iterator().next().getClass(); final Class<?> valueType = value.getClass(); if (keyElementType != valueType) { throw new IllegalArgumentException( "Key element type " + keyElementType + " does not match " + valueType); } return target.put(key, value); } @Override public void putAll(Map<? extends Set<? extends Object>, ? extends Object> m) { for (Entry<? extends Set<? extends Object>, ? extends Object> entry : m.entrySet()) { put(entry.getKey(), entry.getValue()); } }
Here's how it works:
final Map<Set<? extends Object>, Object> map = new FancyTypeMapDecorator(new HashMap<Set<? extends Object>, Object>()); Set<? extends Object> keyA = Collections.singleton(7); map.put(keyA, 42); Set<? extends Object> keyB = Collections.singleton("bogus"); map.put(keyB, 43);
The second put throws an exception.
However, the implementation (and I don’t even mean that it will be unsuccessful for an empty Set as a key), and using the / API starts an alarm ... Do you really want to deal with such a structure? Maybe you need to rethink your problem? What are you really trying to achieve?
source share