0

I have an enum with values like this (the example just shows a few of the values but you will catch on): _800, _830, _900, _24HOURS, CLOSED

These have a corresponding value, so I added to my enum, which you can do in Java, a value field and a getter and setter for the value, like this (for space sake I do not show the getter and setter but they are the standard ones):

 enum Hours {
    _800("08:00"),
    _830("08:30"),
    CLOSED("Closed"),
    APPT("By Appt.")
    // etc
    ;

    Hours(String v) {
        val = v;
    }
    String val;
 }

I also want to be able to go the other direction, that is, if I have a value (e.g. "08:00") I want it to return the enum _800. So to the enum I added a map:

 static Map<String,String> valToEnumMap = new HashMap();

then I added this to my constructor:

    Hours(String v) {
        val = v;
        valToEnumMap.put(v, this);
    }

and a new method:

Hours valToEnum(String v) {
   return valToEnumMap(v);
}

but when I try running it I get an initialization error at the point where it tries to insert into the map. I have tried other things like

 valToEnumMap.put(v, valueOf(name());

but the same error. I did find a workaround but it is very slow, so I wonder what I did wrong? Here is the workaround I used which is slow:

public static OfficeHoursTimes valToEnum(String val) {
        for (OfficeHoursTimes o : OfficeHoursTimes.values()) {
            if (o.getVal().equals(val)) {
                  return o;
            }
        }
        return null;
}

But there has to be a better way

Tony
  • 1,127
  • 1
  • 18
  • 29

2 Answers2

1

The problem is that you're trying to use the map before it's initialized, since your enum instances get created first.

You want to declare your map like this:

static final Map<String,Hours> valToEnumMap = _createValueMap();

and then

private static Map<String,Hours> _createValueMap()
{
    Map<String, Hours> map = new HashMap<>();

    //...iterate through values() and put them all in the map ...

    return map;
}
Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
  • >> The problem is that you're trying to use the map before it's initialized, since your enum instances get created first. - that's not true, add logs and you'll see it – AdamSkywalker May 11 '16 at 11:56
  • @AdamSkywalker According to my logs, Matt is right. Firstly, all enum instances are created. Static fields and static initializer go next. – vojta May 11 '16 at 12:03
  • @vojta https://gist.github.com/AdamSkywalker/11b2c6fcc12a2076c83bbe90883c14bc – AdamSkywalker May 11 '16 at 12:06
  • 1
    @AdamSkywalker, you misunderstand. The map is a static field *in the enum class* – Matt Timmermans May 11 '16 at 12:08
  • @AdamSkywalker see http://stackoverflow.com/a/444000/3899583 – vojta May 11 '16 at 12:12
  • @MattTimmermans ahh, now it makes sence – AdamSkywalker May 11 '16 at 12:14
  • Hey it looks like this will work. For the static map instead of initializing it I just do a static Map valToEnumMap; And then my Constructor: Hours(String v) { val = v; if (valToEnumMap == null) { valToEnumMap = new HashMap<>(); } valToEnumMap.put(v, this); } – Tony May 11 '16 at 12:38
  • @Tony you can do that if the map isn't declared final... but don't -- that's gross – Matt Timmermans May 11 '16 at 12:44
0

At first glance, it seems your map is defined wrong.
Try

static Map<String,Hours> valToEnumMap = new HashMap<String,Hours>();
Robert Kock
  • 5,795
  • 1
  • 12
  • 20
  • sorry. It is HashMap<>() not HashMap(). A typo. It can infer the parameters from the map from the declaration. – Tony May 11 '16 at 12:02