7

我想要一个模拟 EnumMap 的类,但存储 int 值而不是某种对象。现在显然你可以制作一个映射到整数的 EnumMap,但如果可以的话,我想避免很多自动装箱。

所以我想要这样的课程:

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

除了我想制作一个在所有枚举中通用的版本。现在,由于 .values() 和 .ordinal() 方法是由编译器隐式添加的,因此访问它们的唯一方法似乎是使用反射,这会消耗我试图通过避免获得的性能提升自动装箱,但也许我缺少一些东西。

有什么想法吗?

编辑:

我认为我最初的问题不清楚。我想要一个接受(作为通用参数)枚举的类,然后可以使用相同的操作。

所以我可以将它与任何类型的枚举一起使用,而无需每次都为每种枚举编写类。如:

enum Attribute { Height, Weight }

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

IdealClass<Attribute> attributeVersion;

IdealClass<AbilityScore> abilityScoreVersion;

等等。

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

请注意,构造函数需要一个类型 token,这是由于 java 的运行时类型擦除而需要的。

于 2013-04-25T07:42:22.237 回答
1

所有 java 都Enum隐式地 extend java.lang.Enum,所以我认为您正在寻找的是:

public class EnumIntAttributeMap<E extends java.lang.Enum<E>> {
    // [...]
}
于 2013-04-25T07:29:32.037 回答
0

阅读:Oracle 的枚举文档

我认为您可以做一些类似于行星示例的事情:

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 回答
0

这是我个人使用的,并为我在 API 中提供了很好的标准化

通用接口 :

public interface IValueEnum<T> {       
   T value();
}

枚举是这样实现的:

public enum MyEnum implements IValueEnum<Integer> {
   WIDTH(1),
   HEIGHT(2);

   private final int value;
   MyEnum(int value) { this.value = value; }

   @Override
   public Integer value() {
      return value;
   }
}

现在您可以通过 MyEnum.WIDTH.value() 等获得最终值。由于它使用泛型,因此其他枚举可以使用 Longs 或 Strings 或您拥有的任何东西。它允许您在应用程序中拥有一个简单的基于枚举的接口。它还允许您在地图等中完全通用。

编辑:基于新示例

public class IdealClass<T extends Enum> {

  T enumValue;

  public IdealClass() {
  }

}
于 2013-04-25T07:15:24.700 回答