Map with enumeration key and different value types
I want to define a map in Java which keys are enumerated and the value types depend on the key. For example, suppose we have the following enum type:
enum KeyType {
HEIGHT(Integer.class),
NAME(String.class),
WEIGHT(Double.class)
// constructor and getter for Class field
}
and some mapping:
Map< KeyType, Object > map = new EnumMap<>(KeyType.class);
Is there a simple and safe way to create a generic method:
public < T > T get(KeyType key) {
//...
}
which will get the value from this map and apply it to the class of classes?
source to share
UPDATE !!!: With this in mind:
enum KeyType {
//your enums ...
private final Class val;
//constructor ...
//and generic(!) access to the class field:
<T> Class<T> val() {
return val;
}
}
... this is possible:
public <T> T get(KeyType key) {
return (T) key.val().cast(map.get(key));
}
source to share
Your map definition should be
Map< KeyType, ?> map = new EnumMap<>(KeyType.class);
If you specify Object
as a generic type, only valid instances are allowed Object
, not subtypes.
I don't believe there is any direct, general way (no pun intended) of doing what you want. You will need to create some kind of display function that converts the object to the correct type based on an enum.
source to share
You cannot do this with enums. But you can write a "fake" enum (the way Java code did it before Java 1.5, with private constructors and public static instances) and attach a generic type to each constant:
import java.io.Serializable;
import java.util.Map;
public final class KeyType<T>
implements Serializable {
private static final long serialVersionUID = 1;
public static final KeyType<Integer> HEIGHT =
new KeyType<>("HEIGHT", Integer.class);
public static final KeyType<String> NAME =
new KeyType<>("NAME", String.class);
public static final KeyType<Double> WEIGHT =
new KeyType<>("WEIGHT", Double.class);
private static final KeyType<?>[] allValues = {
HEIGHT, NAME, WEIGHT
};
/** @serial */
private final String name;
/** @serial */
private final Class<T> type;
private KeyType(String name,
Class<T> type) {
this.name = name;
this.type = type;
}
public String name() {
return name;
}
public Class<T> getType() {
return type;
}
@Override
public String toString() {
return name();
}
public static KeyType<?>[] values() {
return allValues.clone();
}
public static KeyType<?> valueOf(String name) {
for (KeyType<?> value : allValues) {
if (value.name.equals(name)) {
return value;
}
}
throw new IllegalArgumentException("No such value: \"" + name + "\"");
}
@Override
public boolean equals(Object obj) {
return (obj instanceof KeyType &&
this.name.equals(((KeyType<?>) obj).name));
}
@Override
public int hashCode() {
return name.hashCode();
}
public T getValue(Map<KeyType<?>, ?> map) {
return type.cast(map.get(this));
}
}
source to share