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?

+3


source to share


3 answers


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));
}

      

+1


source


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.

0


source


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));
    }
}

      

0


source







All Articles