Convert integer value to matching Java Enum

Java

Java Problem Overview


I've an enum like this:

public enum PcapLinkType {
  DLT_NULL(0)
  DLT_EN10MB(1)
  DLT_EN3MB(2),
  DLT_AX25(3),
  /*snip, 200 more enums, not always consecutive.*/
  DLT_UNKNOWN(-1);
    private final int value;   

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

Now I get an int from external input and want the matching input - throwing an exception if a value does not exist is ok, but preferably I'd have it be DLT_UNKNOWN in that case.

int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */

Java Solutions


Solution 1 - Java

You would need to do this manually, by adding a a static map in the class that maps Integers to enums, such as

private static final Map<Integer, PcapLinkType> intToTypeMap = new HashMap<Integer, PcapLinkType>();
static {
    for (PcapLinkType type : PcapLinkType.values()) {
        intToTypeMap.put(type.value, type);
    }
}

public static PcapLinkType fromInt(int i) {
    PcapLinkType type = intToTypeMap.get(Integer.valueOf(i));
    if (type == null) 
        return PcapLinkType.DLT_UNKNOWN;
    return type;
}

Solution 2 - Java

There's a static method values() which is documented, but not where you'd expect it: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

enum MyEnum {
	FIRST, SECOND, THIRD;
	private static MyEnum[] allValues = values();
	public static MyEnum fromOrdinal(int n) {return allValues[n];}
}

In principle, you can use just values()[i], but there are rumors that values() will create a copy of the array each time it is invoked.

Solution 3 - Java

You will have to make a new static method where you iterate PcapLinkType.values() and compare:

public static PcapLinkType forCode(int code) {
    for (PcapLinkType typе : PcapLinkType.values()) {
        if (type.getValue() == code) {
            return type;
        }
    }
    return null;
 }

That would be fine if it is called rarely. If it is called frequently, then look at the Map optimization suggested by others.

Solution 4 - Java

You can do something like this to automatically register them all into a collection with which to then easily convert the integers to the corresponding enum. (BTW, adding them to the map in the enum constructor is not allowed. It's nice to learn new things even after many years of using Java. :)

public enum PcapLinkType {
    DLT_NULL(0),
    DLT_EN10MB(1),
    DLT_EN3MB(2),
    DLT_AX25(3),
    /*snip, 200 more enums, not always consecutive.*/
    DLT_UNKNOWN(-1);

    private static final Map<Integer, PcapLinkType> typesByValue = new HashMap<Integer, PcapLinkType>();

    static {
        for (PcapLinkType type : PcapLinkType.values()) {
            typesByValue.put(type.value, type);
        }
    }

    private final int value;

    private PcapLinkType(int value) {
        this.value = value;
    }

    public static PcapLinkType forValue(int value) {
        return typesByValue.get(value);
    }
}

Solution 5 - Java

if you have enum like this

public enum PcapLinkType {
  DLT_NULL(0)
  DLT_EN10MB(1)
  DLT_EN3MB(2),
  DLT_AX25(3),
  DLT_UNKNOWN(-1);

    private final int value;   

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

then you can use it like

PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */

Solution 6 - Java

I know this question is a few years old, but as Java 8 has, in the meantime, brought us Optional, I thought I'd offer up a solution using it (and Stream and Collectors):

public enum PcapLinkType {
  DLT_NULL(0),
  DLT_EN3MB(2),
  DLT_AX25(3),
  /*snip, 200 more enums, not always consecutive.*/
  // DLT_UNKNOWN(-1); // <--- NO LONGER NEEDED
  
  private final int value;
  private PcapLinkType(int value) { this.value = value; }
  
  private static final Map<Integer, PcapLinkType> map;
  static {
    map = Arrays.stream(values())
        .collect(Collectors.toMap(e -> e.value, e -> e));
  }
  
  public static Optional<PcapLinkType> fromInt(int value) {
    return Optional.ofNullable(map.get(value));
  }
}

Optional is like null: it represents a case when there is no (valid) value. But it is a more type-safe alternative to null or a default value such as DLT_UNKNOWN because you could forget to check for the null or DLT_UNKNOWN cases. They are both valid PcapLinkType values! In contrast, you cannot assign an Optional<PcapLinkType> value to a variable of type PcapLinkType. Optional makes you check for a valid value first.

Of course, if you want to retain DLT_UNKNOWN for backward compatibility or whatever other reason, you can still use Optional even in that case, using orElse() to specify it as the default value:

public enum PcapLinkType {
  DLT_NULL(0),
  DLT_EN3MB(2),
  DLT_AX25(3),
  /*snip, 200 more enums, not always consecutive.*/
  DLT_UNKNOWN(-1);
  
  private final int value;
  private PcapLinkType(int value) { this.value = value; }
  
  private static final Map<Integer, PcapLinkType> map;
  static {
    map = Arrays.stream(values())
        .collect(Collectors.toMap(e -> e.value, e -> e));
  }
  
  public static PcapLinkType fromInt(int value) {
    return Optional.ofNullable(map.get(value)).orElse(DLT_UNKNOWN);
  }
}

Solution 7 - Java

As @MeBigFatGuy says, except you can make your static {...} block use a loop over the values() collection:

static {
    for (PcapLinkType type : PcapLinkType.values()) {
        intToTypeMap.put(type.getValue(), type);
    }
}

Solution 8 - Java

You could add a static method in your enum that accepts an int as a parameter and returns a PcapLinkType.

public static PcapLinkType of(int linkType) {
	
	switch (linkType) {
		case -1: return DLT_UNKNOWN
		case 0: return DLT_NULL;
		
		//ETC....
		
		default: return null;
		
	}
}

Solution 9 - Java

This is what I use:

public enum Quality {ENOUGH,BETTER,BEST;
					 private static final int amount = EnumSet.allOf(Quality.class).size();
					 private static Quality[] val = new Quality[amount];
					 static{ for(Quality q:EnumSet.allOf(Quality.class)){ val[q.ordinal()]=q; } }
					 public static Quality fromInt(int i) { return val[i]; }
					 public Quality next() { return fromInt((ordinal()+1)%amount); }
					}

Solution 10 - Java

static final PcapLinkType[] values  = { DLT_NULL, DLT_EN10MB, DLT_EN3MB, null ...}    

...

public static PcapLinkType  getPcapLinkTypeForInt(int num){    
    try{    
       return values[int];    
    }catch(ArrayIndexOutOfBoundsException e){    
       return DLT_UKNOWN;    
    }    
}    

Solution 11 - Java

There is no way to elegantly handle integer-based enumerated types. You might think of using a string-based enumeration instead of your solution. Not a preferred way all the times, but it still exists.

public enum Port {
  /**
   * The default port for the push server.
   */
  DEFAULT("443"),

  /**
   * The alternative port that can be used to bypass firewall checks
   * made to the default <i>HTTPS</i> port.
   */
  ALTERNATIVE("2197");

  private final String portString;

  Port(final String portString) {
    this.portString = portString;
  }

  /**
   * Returns the port for given {@link Port} enumeration value.
   * @return The port of the push server host.
   */
  public Integer toInteger() {
    return Integer.parseInt(portString);
  }
}

Solution 12 - Java

This might not be a great solution, but its working for me:

public enum Type {
        WATER, FIRE, GRASS;

        public static Type getType(int value){
            if(value==WATER.ordinal()){
                return WATER;
            }else if(value==FIRE.ordinal()){
                return FIRE;
            }else if(value==GRASS.ordinal()){
                return GRASS;
            }else {
                return 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
QuestionLykeView Question on Stackoverflow
Solution 1 - JavaMeBigFatGuyView Answer on Stackoverflow
Solution 2 - Java18446744073709551615View Answer on Stackoverflow
Solution 3 - JavaBozhoView Answer on Stackoverflow
Solution 4 - JavaEsko LuontolaView Answer on Stackoverflow
Solution 5 - JavaJack GajananView Answer on Stackoverflow
Solution 6 - JavaBrad CollinsView Answer on Stackoverflow
Solution 7 - JavadtyView Answer on Stackoverflow
Solution 8 - JavaBuhake SindiView Answer on Stackoverflow
Solution 9 - Java18446744073709551615View Answer on Stackoverflow
Solution 10 - Javansfyn55View Answer on Stackoverflow
Solution 11 - JavaBuğra EkukluView Answer on Stackoverflow
Solution 12 - JavaSisiView Answer on Stackoverflow