Get enum by its inner field

后端 未结 5 1226
清歌不尽
清歌不尽 2020-11-27 15:48

Have enum with inner fields, kind of map.

Now I need to get enum by its inner field.

Wrote this:

package test;

/**
 * Test enum to test enum         


        
相关标签:
5条回答
  • 2020-11-27 16:37

    Here is the most convenient way to find enum value by its field:

    public enum TestEnum {
    
      A("EXAMPLE_1", "Qwerty", 1),
      B("EXAMPLE_2", "Asdfgh", 2),
      C("EXAMPLE_3", "Zxcvbn", 3);
    
      private final String code;
      private final String name;
      private final Integer typeID;
    
      TestEnum(String code, String name, Integer typeID) {
        this.code = code;
        this.name = name;
        this.key = typeID;
      }
    
      public String getCode() {
        return code;
      }
    
      public String getName() {
        return name;
      }
    
      public Integer getKey() {
        return key;
      }
    
      public static TestEnum findValueByTypeId(Integer key) {
        return Arrays.stream(TestEnum.values()).filter(v ->
            v.getKey().equals(key)).findFirst().orElseThrow(() ->
            new Exception(String.format("Unknown TestEnum.key: '%s'", key)));
      }
    }
    
    0 讨论(0)
  • 2020-11-27 16:40

    One solution is to add

    public final Test[] TESTS = { null, ONE, TWO, THREE };
    
    public static Test getByNumber(int i) {
        return TESTS[i];
    }
    

    To the enum.

    If the internal data is not an integer, you could have a Map which you populate in a static { ... } initializer. This map could later be used in the getByNumber method above.

    0 讨论(0)
  • 2020-11-27 16:51

    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.

    0 讨论(0)
  • 2020-11-27 16:54

    Although someone has suggested using Map<Integer, TestEnum> think twice about it.

    Your original solution, especially for small enums, may be magnitudes faster than using HashMap.

    HashMap will probably be not faster until your enum contains at least 30 to 40 elements.

    This is one case of "If it ain't broken, don't fix it".

    0 讨论(0)
  • 2020-11-27 16:54

    You should have a HashMap with the numbers as keys and the enum values as values.

    This map can typically be in your repository. Then you can easily replace an int variable from the database with your preferred enum value.

    If your keys (int values) are stored in a database, then I will say its bad design to carry those keys around in an enum on your business layer. If that's the case, I will recommend not to store the int value in the enum.

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