Reputation: 1014
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.
Upvotes: 7
Views: 4114
Reputation: 425358
The key to doing this genetically is knowing the generic bound for an enum:
<T extends Enum<T>>
Your class can work for any enum as follows:
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;
}
}
Note that the constructor requires a type token, which is required due to java's runtime type erasure.
Upvotes: 2
Reputation: 649
This is what I personally use and gives me nice standardization in the APIs
Common Interface :
public interface IValueEnum<T> {
T value();
}
Enums implement it like this:
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;
}
}
Now you can get the final value by going MyEnum.WIDTH.value(), etc. Since it's using generics other enums could use Longs or Strings or what have you. It allows you to have a single simple Enum based interface in the application. It also allows you to be completely generic in your Map, etc.
EDIT: Based on New Example
public class IdealClass<T extends Enum> {
T enumValue;
public IdealClass() {
}
}
Upvotes: 0
Reputation: 48105
This is a solution:
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;
}
}
You will have to initialize the map with the class of the enum as well.
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);
Upvotes: 9
Reputation: 6328
All java Enum
implicitly extend java.lang.Enum
, so I think what you are looking for is:
public class EnumIntAttributeMap<E extends java.lang.Enum<E>> {
// [...]
}
Upvotes: 1
Reputation: 16148
Read this: Oracle's Doc on Enums.
I think you could do something that is similar to the Planets example:
public enum YourEnum{
HEIGHT (0),
WIDTH (1);
private final int index;
YourEnum(int index) {
this.index = index;
}
public int index() { return index; }
}
Upvotes: 0