7

I would like to have a class that emulates the EnumMap, but stores int values instead of some kind of object. Now obviously you could make an EnumMap that maps to Integers, but that's a lot of autoboxing that I'd like to avoid if it's possible to do so.

So I'd like a class like this:

public class EnumIntAttributeMap
{
    enum Attribute
    {
        Height, Weight;
    }

    private final int[] values;

    public EnumIntAttributeMap()
    {
        this.values = new int[Attribute.values().length];
    }

    public int getValue(Attribute a)
    {
        return this.values[a.ordinal()];
    }

    public void setValue(Attribute a, int value)
    {
        this.values[a.ordinal()] = value;
    }
}

Except I'd like to make a version that's generic across all enums. Now, since the .values() and .ordinal() methods are implicitly added by the compiler, it seems like the only way to access them would be with reflection, which would eat up the performance gains I'm trying to gain by avoiding auto-boxing, but maybe there's something I'm missing.

Any thoughts?

EDIT:

I think my initial question was unclear. I would like a class that takes (as a generic parameter) an enum, and then can use the same operations.

So I could use it with any kind of enum without needing to write the class for each kind of enum each time. Such as:

enum Attribute { Height, Weight }

enum AbilityScore {Str, Dex, Con, Int, Wis, Cha}

IdealClass<Attribute> attributeVersion;

IdealClass<AbilityScore> abilityScoreVersion;

and so on.

4

5 に答える 5

9

これは解決策です:

public class EnumIntMap<E extends Enum<E>> {

    private final int[] values;

    public EnumIntMap(Class<E> cls)
    {
        this.values = new int[cls.getEnumConstants().length];
    }

    public int getValue(E a)
    {
        return this.values[a.ordinal()];
    }

    public void setValue(E a, int value)
    {
        this.values[a.ordinal()] = value;
    }
}

列挙型のクラスでもマップを初期化する必要があります。

enum Attribute { Height, Weight }

enum AbilityScore {Str, Dex, Con, Int, Wis, Cha}

EnumIntMap<Attribute> attributeVersion = new EnumIntMap(Attribute.class);

EnumIntMap<AbilityScore> abilityScoreVersion = new EnumIntMap(AbilityScore.class);
于 2013-04-25T07:31:53.167 に答える
2

これを遺伝的に行うための鍵は、列挙型のジェネリック バウンドを知ることです。

<T extends Enum<T>>

クラスは次のように任意の列挙型に対して機能します。

public class EnumIntAttributeMap<T extends Enum<T>> {
    private final int[] values;
    private final Class<T> clazz;

    public EnumIntAttributeMap(Class<T> clazz) {
        this.clazz = clazz;
        this.values = new int[clazz.getEnumConstants().length];
    }

    public int getValue(T a) {
        return this.values[a.ordinal()];
    }

    public void setValue(T a, int value) {
        this.values[a.ordinal()] = value;
    }
}

コンストラクターにはtype tokenが必要であることに注意してください。これは、Java の実行時の型消去のために必要です。

于 2013-04-25T07:42:22.237 に答える
0

これを読んでください: Oracle's Doc on Enums

Planets の例に似たことができると思います。

public enum YourEnum{
    HEIGHT (0),
    WIDTH  (1);

    private final int index;

    YourEnum(int index) {
        this.index = index;
    }
    public int index() { return index; }
}
于 2013-04-25T07:11:08.257 に答える