Can I get an enum based on the value of its field?
For reference, here is an alternative solution with a HashMap:
enum CrimeCategory {
ASBO("Anti Social Behaviour"),
BURG("Burglary"),
CRIMDAM("Criminal Damage And Arson"),
DRUGS("Drugs"),
OTHTHEFT("Other Theft"),
PUPDISOR("Public Disorder And Weapons"),
ROBBERY("Robbery"),
SHOPLIF("Shoplifting"),
VEHICLE("Vehicle Crime"),
VIOLENT("Violent Crime"),
OTHER("Other Crime");
private static final Map<String, CrimeCategory> map = new HashMap<>(values().length, 1);
static {
for (CrimeCategory c : values()) map.put(c.category, c);
}
private final String category;
private CrimeCategory(String category) {
this.category = category;
}
public static CrimeCategory of(String name) {
CrimeCategory result = map.get(name);
if (result == null) {
throw new IllegalArgumentException("Invalid category name: " + name);
}
return result;
}
}
Get enum by its inner field
You can use a static Map<Integer,TestEnum>
with a static
initializer that populates it with the TestEnum
values keyed by their number
fields.
Note that findByKey
has been made static
, and number
has also been made final
.
import java.util.*;
public enum TestEnum {
ONE(1), TWO(2), SIXTY_NINE(69);
private final int number;
TestEnum(int number) {
this.number = number;
}
private static final Map<Integer,TestEnum> map;
static {
map = new HashMap<Integer,TestEnum>();
for (TestEnum v : TestEnum.values()) {
map.put(v.number, v);
}
}
public static TestEnum findByKey(int i) {
return map.get(i);
}
public static void main(String[] args) {
System.out.println(TestEnum.findByKey(69)); // prints "SIXTY_NINE"
System.out.println(
TestEnum.values() == TestEnum.values()
); // prints "false"
}
}
You can now expect findByKey
to be a O(1)
operation.
References
- JLS 8.7 Static initializers
- JLS 8.9 Enums
Related questions
- Static initalizer in Java
- How to Initialise a static Map in Java
Note on values()
The second println
statement in the main
method is revealing: values()
returns a newly allocated array with every invokation! The original O(N)
solution could do a little better by only calling values()
once and caching the array, but that solution would still be O(N)
on average.
Getting Enum value by another value
The ENUM types has the method values
, which you can use to extract all the enum values and compare their identifier against the one that you have passed by the method parameter, namely:
public MyEnum getEnum(String identifier){
for(MyEnum e : MyEnum.values())
if(e.identifier.equals(identifier))
return e;
return null;
}
or even better:
public static Optional<MyEnum> getEnum(String identifier){
return Arrays.stream(MyEnum.values()).filter(i -> i.identifier.equals(identifier)).findFirst();
}
This way you make it clear on the method signature that you might or not find the enum.
How to get an enum value from a string value in Java
Yes, Blah.valueOf("A")
will give you Blah.A
.
Note that the name must be an exact match, including case: Blah.valueOf("a")
and Blah.valueOf("A ")
both throw an IllegalArgumentException
.
The static methods valueOf()
and values()
are created at compile time and do not appear in source code. They do appear in Javadoc, though; for example, Dialog.ModalityType
shows both methods.
get enum name from enum value
Since your 'value' also happens to match with ordinals you could just do:
public enum RelationActiveEnum {
Invited,
Active,
Suspended;
private final int value;
private RelationActiveEnum() {
this.value = ordinal();
}
}
And getting a enum from the value:
int value = 1;
RelationActiveEnum enumInstance = RelationActiveEnum.values()[value];
I guess an static method would be a good place to put this:
public enum RelationActiveEnum {
public static RelationActiveEnum fromValue(int value)
throws IllegalArgumentException {
try {
return RelationActiveEnum.values()[value]
} catch(ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Unknown enum value :"+ value);
}
}
}
Obviously this all falls apart if your 'value' isn't the same value as the enum ordinal.
How to get the enum type by its attribute?
All you need to do is add a default case so the method always returns something or throws an exception:
AreaCode area(int n){
switch (n) {
case 7927: return AreaCode.area1;
case 7928: return AreaCode.area2;
case 7929: return AreaCode.area3;
default: return null;
}
}
or perhaps better
AreaCode area(int n){
switch (n) {
case 7927: return AreaCode.area1;
case 7928: return AreaCode.area2;
case 7929: return AreaCode.area3;
default: throw new IllegalArgumentException(String.valueOf(n));
}
}
set class fields based on enum value
Use a BiConsumer<Tempclass, String>
taking an instance of TempClass
and a String
and set the appropriate field in the class.
VALUE1(Tempclass::getField1, Tempclass::setField1),
VALUE2(Tempclass::getField2, Tempclass::setField2);
private final BiConsumer<Tempclass, String> setter;
Get the setter from the enum and pass the values to the accept
method of the BiConsumer.
enumInstance.getSetter().accept(tempClassInstance, "some-value");
Get int value from enum in C#
Just cast the enum, e.g.
int something = (int) Question.Role;
The above will work for the vast majority of enums you see in the wild, as the default underlying type for an enum is int
.
However, as cecilphillip points out, enums can have different underlying types.
If an enum is declared as a uint
, long
, or ulong
, it should be cast to the type of the enum; e.g. for
enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};
you should use
long something = (long)StarsInMilkyWay.Wolf424B;
How can I lookup a Java enum from its String value?
Use the valueOf
method which is automatically created for each Enum.
Verbosity.valueOf("BRIEF") == Verbosity.BRIEF
For arbitrary values start with:
public static Verbosity findByAbbr(String abbr){
for(Verbosity v : values()){
if( v.abbr().equals(abbr)){
return v;
}
}
return null;
}
Only move on later to Map implementation if your profiler tells you to.
I know it's iterating over all the values, but with only 3 enum values it's hardly worth any other effort, in fact unless you have a lot of values I wouldn't bother with a Map it'll be fast enough.
Related Topics
How to Use a Java8 Lambda to Sort a Stream in Reverse Order
How to Get the Count of Line in a File in an Efficient Way
Jtable Getselectedrow Does Not Return the Selected Row Index
"Faceted Project Problem (Java Version Mismatch)" Error Message
Generate JPA 2 Entities from Existing Database
Differencebetween Lowagie and Itext
How to Open a Txt File and Read Numbers in Java
Java Parsing Xml Document Gives "Content Not Allowed in Prolog." Error
Why Are Class Static Methods Inherited But Not Interface Static Methods
File Path Windows Format to Java Format
Why Are Java 8 Lambdas Invoked Using Invokedynamic
Where Is the Correct Location to Put Log4J.Properties in an Eclipse Project
How to Serialize Only the Id of a Child with Jackson
Why Do Consumers Accept Lambdas with Statement Bodies But Not Expression Bodies