Psl
Psl

Reputation: 3920

use Enum class instead of a Map for holding constants

I have a map like below to hold some constant values. Keeping values in a Map is not a good practice. Instead I can use an enum to hold these values. But I'm a bit confused about how to create an enum for the below mapping

//Map to store the events
public static final Map<String, Integer[]> OLYMPICS_SPORT_ID_PARAMS = new HashMap<>();
public static final Map<String, Integer[]> OLYMPICS_EVENT_ID_PARAMS = new HashMap<>();
public static final Map<String, Integer[]> OLYMPICS_PHASE_ID_PARAMS = new HashMap<>();
static {
    OLYMPICS_SPORT_ID_PARAMS.put("sportId", VALID_SPORT_IDS);
    OLYMPICS_EVENT_ID_PARAMS.put("n_EventID", VALID_EVENT_IDS);
    OLYMPICS_PHASE_ID_PARAMS.put("n_EventPhaseID", VALID_EVENT_PHASE_IDS);
}

public static final Map<String, Map<String, Integer[]>> OLYMPICS_EVENTS_MAP = new HashMap<>();
static {
    OLYMPICS_EVENTS_MAP.put("sportId", OLYMPICS_SPORT_ID_PARAMS);
    OLYMPICS_EVENTS_MAP.put("eventId", OLYMPICS_EVENT_ID_PARAMS);
    OLYMPICS_EVENTS_MAP.put("eventPhaseId", OLYMPICS_PHASE_ID_PARAMS);
}

Any idea to create an ENUM class to map OLYMPICS_EVENTS_MAP ?

Upvotes: 2

Views: 5092

Answers (4)

zlakad
zlakad

Reputation: 1384

In my HO, generally you want to write the statement like this:

OlimpicSportEvent olSpEv = new OlimpicSportEvent(
                Sport.ATHLETIC, Event.SPRINT_100_M, Phase.SEMIFINAL);

To be able to do so, you have to be sure that your Event.SPRINT_100_M have Phase.SEMIFINAL AND Sport.ATHLETIC have Event.SPRINT_100_M.

I'll not write the entire code here, but I'd try to explain my approach. First of all, you should write not only one, but three enums. I hope the code will tell you more than words. E.g.

public enum Sport {
    ATHLETIC    (0,
                Arrays.asList(  Event.SPRINT_100_M,
                                Event.MARATHON)
                ),
    //...
    SOCCER      (109,
                Arrays.asList(  Event.TEAM_MATCH)
                );

    private final int id;
    private final List<Event> events;

    Sport(int id, List<Event> events){
        this.id = id;
        this.events = events;
    }

    public int getId(){
        return id;
    }

    protected List<Event> getEvents(){
        return this.events;
    }

}

enum Event {
    SPRINT_100_M, // similar to enum Sport, params goes here
    //...
    TEAM_MATCH,
    MARATHON;
}

enum Phase {
    FIRST_ROUND, // params goes here
    //...
    SEMIFINAL,
    FINAL
}

As you see, I only wrote the enum Sport to the end. Now, I wrote 'test' sample like this (note that you must implement the validate method to meet your request as well as you must write the complete code for Event and Phase enums...

public class Answer {

    static class OlimpicSportEvent {
        //private other field 
        //private other field 
        private final Sport sport;
        private final Event event;
        private final Phase phase;

        OlimpicSportEvent(Sport sport, Event event, Phase phase) throws Exception{
            this.sport = sport;
            this.event = event;
            this.phase = phase;

            if(!this.validate()){
                throw new Exception();
            }
        }

        public Sport getSport() {
            return sport;
        }

        public Event getEvent() {
            return event;
        }

        public Phase getPhase() {
            return phase;
        }

        private boolean validate(){
            return this.sport.getEvents().contains(this.event);
        }
    }

    public static void main(String[] args) {

        try {
            OlimpicSportEvent olSpEv = new OlimpicSportEvent(
                    Sport.ATHLETIC, Event.SPRINT_100_M, Phase.SEMIFINAL);
            System.out.println("olSpEv created!");
            // do whatever you want
        } catch (Exception ex) {
            System.out.println("olSpEv invalid!");
            // handle ex
        }

    }

}

Upvotes: 1

daniu
daniu

Reputation: 14999

You'd define it like this

enum IdParams {
    OLYMPICS_SPORT_ID_PARAMS(VALID_SPORT_IDS),
    OLYMPICS_EVENT_ID_PARAMS(VALID_EVENT_IDS),
    OLYMPICS_PHASE_ID_PARAMS(VALID_EVENT_PHASE_IDS);

    private Integer[] params;
    private IdParams(Integer[] p) {
        params = p;
    }
    public Integer[] getParameters() {
        return params;
    }
}

Be aware that an array is a very dangerous thing to have around like this though; client classes will be able to manipulate the individual values. I recommend you make it a List<Integer> and return an unmodifiable version:

    List<Integer> params; 
    // ...
    private IdParams(Integer[] p) {
        params = new ArrayList<>(Arrays.asList(p));
    }
    public List<Integer> getParamters() {
        return Collections.unmodifiableList(params);
    }

Upvotes: 2

ernest_k
ernest_k

Reputation: 45319

The first option to replace your initial implementation would be to use an enum map, java.util.EnumMap<K, V>, which is aware of the enum type.

However, if you need to use an enum for this, a valid enum recording both the ID and the int array could look like:

enum OlympicEvents {
    OLYMPICS_EVENTS_MAP("sportId", new Integer[] { 1, 2, 3 }), 
    OLYMPICS_EVENT_ID_PARAMS("eventId", new Integer[] { 1, 2, 3 }), 
    OLYMPICS_PHASE_ID_PARAMS("eventPhaseId", new Integer[] { 1, 2, 3 });


    private String eventId;

    private Integer[] eventParams;

    private OlympicEvents (String eventId, Integer[] eventParams) {

        this.eventId = eventId;
        this.eventParams = eventParams;
    }

    public String getEventId() {

        return eventId;
    }

    public Integer[] getEventParams() {

        return eventParams;
    }
}

Upvotes: 1

Dumbo
Dumbo

Reputation: 1827

You can use the ENUM class to store your constants by creating constructor and getters for the ENUM with body. Like this:

public enum MyEnum {

    FIRST("1", "my first"),
    SECOND("2", "my second"),
    THIRD("3", "my third");

    private final String value;
    private final String description;

    MyEnum(String value, String description) {
        this.value = value;
        this.description = description;
    }

    public String getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }
}  

And access your value or description by using: MyEnum.FIRST.getValue();.

Upvotes: 3

Related Questions