2

I have switch case with 50 String checks in case as given below:

switch(str){
  case "Employee number":
    //setter
    break;
}

I want to put them in Enum with description as given below:

enum myenum{
        EMPLOYEE_NUMBER("Employee number"),
        FIRST_NAME("First name");   

        private String desc;
        private myenum(String desc) {
            this.setDesc(desc);
        }
        public String getDesc() {
            return desc;
        }
        public void setDesc(String desc) {
            this.desc = desc;
        }

    }

Now, From Source i am getting String "Employee Number" and i want to write switch case in such a way that we can compare description of enum with incoming string input in Case.

I tried some methods in enum

myenum.valueOf(a); // This return enum value but not parameter
myenum.values // This is array which is also not useful here

Kindly suggest how it is achievable in Enum? I am using Java 8

and also suggest Is enum right choice here? or shall i create Static string class with all 50 values or any other best wayout?

fatherazrael
  • 5,511
  • 16
  • 71
  • 155
  • @Tim: Kindly don't mark it duplicate. Neither that question and nor any of answer covers anything related to enum parameter. Kindly go through question please. I have already gone through some of threads and none of them covering this aspect. – fatherazrael Jul 25 '19 at 04:36
  • Have you gone through this one? https://stackoverflow.com/a/1080912/869736 – Louis Wasserman Jul 25 '19 at 04:45

1 Answers1

4

You can first get the MyEnum instance from String str and then use switch by MyEnum, like below:

enum MyEnum {
    EMPLOYEE_NUMBER("Employee number"),
    FIRST_NAME("First name");

    private String desc;

    MyEnum(String desc) {
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }

    public static Optional<MyEnum> fromDesc(String desc) {
        return Stream.of(MyEnum.values()).filter(myEnum -> myEnum.getDesc().equals(desc)).findFirst();
    }

}

And then in your main code:

Optional<MyEnum> maybeMyEnum = MyEnum.fromDesc(str);
if (maybeMyEnum.isPresent()) {
    switch(maybeMyEnum.get()){
        case EMPLOYEE_NUMBER:
            //setter
            break;
    }
}


UPD 1:
As @Ole V.V. - stated in a comment, using Optional.get() and Optional.isPresent() is not a best practice - the idea is - you have to defer getting value out of Optional as much as possible. Also Optional.get() violates getter contract:

Optional.get() is an "attractive nuisance" and is too tempting for programmers, leading to frequent errors. People don't expect a getter to throw an exception.

From JDK-8140281 : (opt) add no-arg orElseThrow() as preferred alternative to get()

So given that, you can rewrite your code as:

...
MyEnum.fromDesc(str)
    .ifPresent(SomeClass::methodWithSwitchStatement);
...
class SomeClass {
    public static void methodWithSwitchStatement(MyEnum myEnum) {
        switch(myEnum){
            case EMPLOYEE_NUMBER:
               //setter
               break;
        }
    }
}
...

The names in the above code are just for examples - you shouldn't use such names in your project.


UPD 2:
Here is the version of MyEnum with caching:

enum MyEnum {
    EMPLOYEE_NUMBER("Employee number"),
    FIRST_NAME("First name");

    private static final Map<String, MyEnum> cacheByDesc;
    static {
        cacheByDesc = Stream.of(MyEnum.values()).collect(Collectors.toMap(MyEnum::getDesc, e -> e));
    }

    private String desc;

    MyEnum(String desc) {
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }

    public static Optional<MyEnum> fromDesc(String desc) {
        return Optional.ofNullable(desc)
                .map(cacheByDesc::get);
    }

}
Vüsal
  • 2,580
  • 1
  • 12
  • 31
  • Thanks Vusal. Let me try this. Any performance overhead, if already calculated? – fatherazrael Jul 25 '19 at 04:50
  • 1
    You can build some `Map` from `MyEnum.values()` and reduce runtime complexity of `fromDesc` from `O(n)` to `O(1)` - where `n` - is the number of entries in `MyEnum`, as shown here: https://stackoverflow.com/questions/1080904/how-can-i-lookup-a-java-enum-from-its-string-value/1080912#1080912 – Vüsal Jul 25 '19 at 04:52
  • Thanks. Working fine both way. I hope my lead will not say to use simple 50 Strings only in case or standard old way i.e static constant in file. :) – fatherazrael Jul 25 '19 at 05:05
  • 2
    More conventional (and a bit shorter): `maybeMyEnum.ifPresent(mEnum -> { switch (mEnum) { /* … */ } });`. Rule of thumb: rarely use `isPresent` and `get`, they are low-level. – Ole V.V. Jul 25 '19 at 08:58
  • 2
    Yeah, you can add a `Map` from string to enum constant, or you implement `fromDesc` with a `switch` statement… – Holger Jul 25 '19 at 11:18
  • @Vusal: Can you also bring Map to this answer which is somewhere in another link according to your example? It will make it full fledged answer too – fatherazrael Jul 25 '19 at 12:25