2014/09/21

Lookup Methods in Enums

There is often the need to map numeric values of a Java enum to the enum instances, aka lookup.
It seems as a simple task yet I saw and even used different approaches until finally came with something acceptable. Below is short comparison of witnessed approaches, ending with what I see as the best one.



First the list approaches I tried (or witnessed) and refused.
In the following examples the numeric value to look-up is in variable code, method getCode() returns the numeric value of the enumeration instance.

Rummaging Through the Values Using For Loop

for(EnumType value : values)
{ 
  if (value.getCode()==code) { return value; } 
}

Pros: zero maintenance
Cons: waste of cycles

Look-up Values Hard-Coded in the Switch Statement

public static EnumType fromInt (int code) 
{
  EnumType result = UNKNOWN; // fallback value
  switch (code)
  {
    case 1: result = ENUM_ONE; break;
    //... 
  }
  return result;
}

Pros: fast lookup
Cons: needs maintenance, needs test for assuring the conversion is reflexive (all known values are converted to proper instances)

Storing Values in Hard-Coded Map

private static Map<Integer,EnumType> lookupMap = new HashMap<>()
static 
{
  lookupMap.put(1,ENUM_ONE);
  lookupMap.put(2,ENUM_TWO);
}

public static EnumType fromInt (int code) 
{
   return lookupMap.get(code);
} 
 
Pros: fast lookup
Cons: needs maintenance


Using Load-Time Constructed Map

The solution merging the positives of fast lookup and zero maintenance uses Map populated with values in static initialization block. This is possible to do for enums as at the moment when the map is going to be filled, all the enum constants are already instantiated (guaranteed, by JVM).
private static Map<Integer,EnumType> lookupMap;

static
{ 
  EnumType[] values = values();
  lookupMap = new HashMap<Integer,EnumType>(values.length);
  for (EnumType value : values)
  {
    lookupMap.put(value.getCode(),value);
  }
}

public static EnumType fromInt (int code) 
{
   return lookupMap.get(code);
}