I have the enum
as:
public enum EnumStatus {
PASSED(40L, \"Has Passed\"),
AVERAGE(60L, \"Has Average Marks\"),
GOOD(80L, \"Has Good
This can be done using a static map along with a static initializer:
public enum EnumStatus {
PASSED(40L, "Has Passed"),
AVERAGE(60L, "Has Average Marks"),
GOOD(80L, "Has Good Marks");
private static final Map<Long, EnumStatus> byId = new HashMap<Long, EnumStatus>();
static {
for (EnumStatus e : EnumStatus.values()) {
if (byId.put(e.getId(), e) != null) {
throw new IllegalArgumentException("duplicate id: " + e.getId());
}
}
}
public static EnumStatus getById(Long id) {
return byId.get(id);
}
// original code follows
private java.lang.String name;
private java.lang.Long id;
EnumStatus(Long id, java.lang.String name) {
this.name = name;
this.id = id;
}
public java.lang.String getName() {
return name;
}
public java.lang.Long getId() {
return id;
}
}
This will give an O(1)
getById()
method, and will automatically detect if you accidentally have duplicate ids in the enum.
Since Java 8 introduced Optional
you can use it as a return type. Consider implementing like:
public static Optional<EnumStatus> fromId(Long id) {
for (EnumStatus e: values()) {
if (e.id.equals(id)) {
return Optional.of(e);
}
}
return Optional.empty();
}
Or using Stream API:
public static Optional<EnumStatus> fromId(Long id) {
return Stream.of(values())
.filter(e -> e.id.equals(id))
.findFirst();
}
In the book Effective Java 3rd Edition the author Joshua Bloch recommends an effective solution which also uses Optional
as a return type:
private static final Map<String, Operation> stringToEnum =
Stream.of(values()).collect(
toMap(Object::toString, e -> e));
public static Optional<Operation> fromString(String symbol) {
return Optional.ofNullable(stringToEnum.get(symbol));
}
Bloch's reasoning for using Optional
:
... note that the
fromString
method returns anOptional<Operation>
. This allows the method to indicate that the string that was passed in does not represent a valid operation, and it forces the client to confront this possibility
Define contract
/**
* Contract that will allow Types with id to have generic implementation.
*/
public interface IdentifierType<T> {
T getId();
}
Apply contract
public enum EntityType implements IdentifierType<Integer> {
ENTITY1(1, "ONE), ENTITY2(2, "TWO");
private Integer id;
private String name;
private EntityType(int id, String name) {
this.id = id;
this.name = name;
}
public static EntityType valueOf(Integer id) {
return EnumHelper.INSTANCE.valueOf(id, EntityType.values());
}
@Override
public Integer getId() {
return id;
}
}
Helper/Util
public enum EnumHelper {
INSTANCE;
/**
* This will return {@link Enum} constant out of provided {@link Enum} values with the specified id.
* @param id the id of the constant to return.
* @param values the {@link Enum} constants of specified type.
* @return the {@link Enum} constant.
*/
public <T extends IdentifierType<S>, S> T valueOf(S id, T[] values) {
if (!values[0].getClass().isEnum()) {
throw new IllegalArgumentException("Values provided to scan is not an Enum");
}
T type = null;
for (int i = 0; i < values.length && type == null; i++) {
if (values[i].getId().equals(id)) {
type = values[i];
}
}
return type;
}
}
Sometimes the enum's ordinal has a clear relationship with this kind of ids, enabling a neat way to get O(1) in these methods. In your code, it is clear that
EnumStatus.X = 40 + 20 * ordinal
,
so you can leverage the static array that is generated under the hoods.
public static EnumStatus fromId(Long id) {
int index = (id - 40L) / 20L;
return values()[index];
}
Add a method in your Enum
and get it by passing ids.
public static ArrayList<EnumStatus> getEnumStatusById(ArrayList<Long> idList) {
ArrayList<EnumStatus> listById = new ArrayList();
for(EnumStatus es: EnumStatus.values()) {
if( idList.contains(es.getId())) {
listById.add(es);
}
}
return listById;
}
Nihal, you have got a lot of replies answering how to find the right enum element. But I have the feeling you wanted also to have the name of the element like "PASSED" instead of "Has Passed".
Please call for .name() to get "PASSED".
Extending the answer of Josua: getById(40L).name();
and EnumStatus.PASSED.getName() to get in your case "Has Passed".