How to retrieve Enum name using the id?

前端 未结 11 1582
一整个雨季
一整个雨季 2020-12-05 13:11

I have the enum as:

public enum EnumStatus {

    PASSED(40L, \"Has Passed\"),
    AVERAGE(60L, \"Has Average Marks\"),
    GOOD(80L, \"Has Good         


        
相关标签:
11条回答
  • 2020-12-05 13:47

    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.

    0 讨论(0)
  • 2020-12-05 13:47

    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 an Optional<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

    0 讨论(0)
  • 2020-12-05 13:48

    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;
      }
    }
    
    0 讨论(0)
  • 2020-12-05 13:49

    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];
    }
    
    0 讨论(0)
  • 2020-12-05 13:56

    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;
    }
    
    0 讨论(0)
  • 2020-12-05 13:56

    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".

    0 讨论(0)
提交回复
热议问题