Home > other >  Java - enum where one variable can be multi-valued
Java - enum where one variable can be multi-valued

Time:01-12

I have an enum like below. Until recently, all variables were single-valued. However, now TYPE4 can have one of three acceptable values. I was hoping to simply modify this enum to accommodate for TYPE4, but thinking perhaps having only one type that is multi-valued means I need to use an object for mapping rather than an enum. I would be grateful for any insights. Thank you.

public enum Record {
    TYPE1("TYPE1"),
    TYPE2("TYPE2"),
    TYPE3("TYPE3"),
    TYPE4_MULTI(TYPE_A or TYPE_B or TYPE_C); 

    private final String value;
    public static final Map<Record, String> enumMap = new EnumMap<Record, String>(
        Record.class);

    static {
        for (Record e : Record.values())
            enumMap.put(e, e.getValue());
    }

    Record(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

Operationally, I use this enum in a factory class to determine which of 4 types of subclasses I should instantiate. I do this by have each of the subclasses know its own type like this:

@Override
public String getType() {
    return Record.TYPE1.getValue();
}

,and then the factory class pre-builds a set of the subclasses like this:

@Component
public class RecordProcessorFactory {

    @Autowired
    public RecordProcessorFactory(List<RecordProcessor> processors) {
        for (RecordProcessor recordProcessor : processors) {
            processorCache.put(recordProcessor.getType(), recordProcessor);
        }
    }

    private static final Map<String, RecordProcessor> processorCache = new HashMap<String, RecordProcessor>();

    public RecordProcessor getSyncProcessor(String type) {
        RecordProcessor service = processorCache.get(type);
        if(service == null) throw new RuntimeException("Unknown service type: "   type);
        return service;
    }
}

CodePudding user response:

You could use a String array to store multiple values, note that your logic may change with enumMap that way.

public enum Record {
    TYPE1("TYPE1"),
    TYPE2("TYPE2"),
    TYPE3("TYPE3"),
    TYPE4_MULTI("TYPE_A", "TYPE_B", "TYPE_C");

    private final String[] values;
    public static final Map<Record, String[]> enumMap = new EnumMap<Record, String[]>(Record.class);

    static {
        for (Record e : Record.values())
            enumMap.put(e, e.getValues());
    }


    Record(String... values) {
        this.values = values;
    }

    public String[] getValues() {
        return values;
    }
}

In case you need to get the Enum from a String value, you could add this static method:

public static Optional<Record> optionalValueOf(final String value) {
    for (Record record : values()) {
        for (String recordValue : record.values) {
            if (null == value && null == recordValue || value.equals(recordValue)) {
                return Optional.of(record);
            }
        }
    }
    return Optional.empty();
}

CodePudding user response:

I think it's better to encapsulate values in the enum. It should be immutable (array is not immutable data storage).

@lombok.Getter
public enum Record {
    TYPE1("TYPE1"),
    TYPE2("TYPE2"),
    TYPE3("TYPE3"),
    TYPE4_MULTI("TYPE_A", "TYPE_B", "TYPE_C");

    // immutable list
    private final List<String> values;

    Record(String... values) {
        this.values = Arrays.stream(values)
                            .collect(Collectors.toList());
    }

}

P.S. Map<Record, String> enumMap I think is useless, because you have a Record already and all you need just call record.getValues() instead of Record.enumMaps.get(record). Also, this is breakes OOP encapsulation.

  • Related