Getting enum associated with int value

JavaEnums

Java Problem Overview


Previously, I had my LegNo enums defined simply as:

NO_LEG, LEG_ONE, LEG_TWO

and by calling return LegNo.values()[i];, I was able to get the value associated with each enum.

But now I've decided I want the LegNo enum NO_LEG to be the int -1 instead of 0 so I decided to use a private constructor to initialise and set its int value

NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

private LegNo(final int leg) { legNo = leg; }

the only thing now is that because I'm doing it this way the values() method will not work for the NO_LEG enum. How do I get the enum associated with the int? Is there any efficient way of doing this other than using a case switch statement or an if-elseif-elseif

I can see a lot of SO questions to do with getting the int value from the enum, but I'm after the reverse.

Java Solutions


Solution 1 - Java

EDIT August 2018

Today I would implement this as follows

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private final int value;

    LegNo(int value) {
        this.value = value;
    }

    public static Optional<LegNo> valueOf(int value) {
        return Arrays.stream(values())
            .filter(legNo -> legNo.value == value)
            .findFirst();
    }
}

You'll have to maintain a mapping inside the enum.

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
    
    private int legNo;
    
    private static Map<Integer, LegNo> map = new HashMap<Integer, LegNo>();
    
    static {
        for (LegNo legEnum : LegNo.values()) {
            map.put(legEnum.legNo, legEnum);
        }
    }

    private LegNo(final int leg) { legNo = leg; }
    
    public static LegNo valueOf(int legNo) {
        return map.get(legNo);
    }
}

The static block will be invoked only once, so there is practically no performance issue here.

EDIT: Renamed the method to valueOf as it is more inline with other Java classes.

Solution 2 - Java

You could also include a static method in the enum that iterates through all members and returns the correct one.

public enum LegNo {
   NO_LEG(-1),
   LEG_ONE(1),
   LEG_TWO(2);
   
   private int legIndex;

   private LegNo(int legIndex) { this.legIndex = legIndex; }

   public static LegNo getLeg(int legIndex) {
      for (LegNo l : LegNo.values()) {
          if (l.legIndex == legIndex) return l;
      }
      throw new IllegalArgumentException("Leg not found. Amputated?");
   }
}

Now, if you want to get an Enum value by the integer, you just use:

int myLegIndex = 1; //expected : LEG_ONE
LegNo myLeg = LegNo.getLeg(myLegIndex);

Solution 3 - Java

adarshr's answer adapted to Java 8:

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;

import java.util.Map;

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private final int legNo;

    private final static Map<Integer, LegNo> map =
            stream(LegNo.values()).collect(toMap(leg -> leg.legNo, leg -> leg));

    private LegNo(final int leg) {
        legNo = leg;
    }

    public static LegNo valueOf(int legNo) {
        return map.get(legNo);
    }
}

Solution 4 - Java

You can also access Enum value corresponding to given integer value simply by calling values() method on enum LegNo. It returns field of LegNo enums: LegNo.values()[0]; //returns LEG_NO LegNo.values()[1]; //returns LEG_ONE LegNo.values()[2]; //returns LEG_TWO

Not precisely the thing he was looking for, but pretty close though and very simple indeed. (Although the subject is dead it might be useful for someone else.)

Solution 5 - Java

Java 8 way with default value:

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private final int legNo;

    LegNo(int legNo) {
        this.legNo = legNo;
    }

    public static LegNo find(int legNo, Supplier<? extends LegNo> byDef) {
        return Arrays.asList(LegNo.values()).stream()
                .filter(e -> e.legNo == legNo).findFirst().orElseGet(byDef);
    }
}

to call:

LegNo res = LegNo.find(0, () -> LegNo.NO_LEG);

or with Exception:

LegNo res = LegNo.find(0, () -> {
    throw new RuntimeException("No found");
});

Solution 6 - Java

public enum LegNo {

  NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

  private final int code;

  LegNo(int code) {
    this.code = code;
    ReverseStorage.reverseMap.put(code, this);
  }

  public static Optional<LegNo> getByCode(int code) {
    return Optional.ofNullable(ReverseStorage.reverseMap.get(code));
  }

  private static final class ReverseStorage {
    private static final Map<Integer, LegNo> reverseMap = new LinkedHashMap<>();
  }
}

Solution 7 - Java

Since your enum only contains 3 elements, the fastest way will be to just use a series of if else, like you suggested.

edit: the answer that adarshr provided is better suited for general cases, where there are many enum values, but I think it is an overkill for your problem.

Solution 8 - Java

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private int legNo;

    private LegNo(int leg) { legNo = leg; }

    public static LegNo valueOf(int legNo) {
        for (LegNo leg : LegNo.values()) {
            if (leg.legNo == legNo) return leg;
        }	
    }
}

assert LegNo.valueOf(2) == LegNo.LEG_TWO
assert LegNo.valueOf(3) == null

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionL-SamuelsView Question on Stackoverflow
Solution 1 - JavaadarshrView Answer on Stackoverflow
Solution 2 - JavaMike AdlerView Answer on Stackoverflow
Solution 3 - JavaMarcinView Answer on Stackoverflow
Solution 4 - JavaTadeasView Answer on Stackoverflow
Solution 5 - JavaDmitry SokolyukView Answer on Stackoverflow
Solution 6 - JavaAndrey LebedenkoView Answer on Stackoverflow
Solution 7 - JavaDieterDPView Answer on Stackoverflow
Solution 8 - JavaTom BView Answer on Stackoverflow