Перечень справок / советов - Java - PullRequest
2 голосов
/ 16 марта 2012

Можно ли использовать перечисление в следующих обстоятельствах:

Допустим, у вас есть определенное количество предопределенных «типов чтения».Примерными типами чтения могут быть: Diagnostic, KWH, MaxDemand, OnPeak и т. Д. И для каждого из этих типов чтения есть «TIMTagNumber», который является протоколом для извлечения каждого предопределенного типа чтения.

Например, TIMTagNumber 1100 будет получать тип чтения Диагностический TIMTagNumber 1300 будет получать тип чтения KWH.Проблема заключается в том, что предопределенный тип чтения может иногда быть получен более чем одним TIMTagNumber.

Я хочу создать перечисление ReadType, которое будет определять каждый тип чтения и все TIMTagNumbers, которые могут использоватьсячтобы получить это чтение.Можете ли вы использовать перечисление таким образом?

public enum ReadType{
    KWH(1300)
    Diagnostic(1100)
    ReadType3(1400, 1401) // This read can be retrieved by both 1400 and 1401
}

Если перечисление не подходит, существует ли элегантный или эффективный способ определения этих типов чтения?Общий желаемый результат всего этого заключается в распознавании того, какой тип чтения он основан на TIMTagNumbers.

IE. Учитывая 1400 ИЛИ 1401, вы знаете, что это «ReadType3».

Ответы [ 5 ]

4 голосов
/ 16 марта 2012

Ты можешь сделать это?Да.Правильное ли это решение будет зависеть от того, хотите ли вы соединить эти TIMTagNumbers с типом чтения.Если нет, то, вероятно, будет достаточно простого Map<Integer, ReadType>.

Вот как вы можете это сделать:

public static enum MyEnum {
    KWH(1300), 
    Diagnostic(1100),
    ReadType3(1400, 1401);

    private Set<Integer> timTagNumbers;

    MyEnum(Integer... timTagNumbers) {
        this.timTagNumbers = new HashSet<Integer>(Arrays.asList(timTagNumbers));
        //add check to make sure that values are unique across all instances
    }

    public static MyEnum forTIMTagNumber(int num) {
        for ( MyEnum readType : values() ) {
             if ( readType.timTagNumbers.contains(num) ) {
                 return readType;
             }
        }
        throw new NoSuchElementException("No ReadType matching TIMTagNumber " + num);
    }
}

//...
int timTagNumber = 1400;
ReadType readType = ReadType.forTIMTagNumber(timTagNumber);

Как я уже говорил выше, этот стиль хорошо работает, когда данные и типы перечисленийнеразрывно связаны уже.Это не будет хорошо, если тип перечисления отделен от отображенных значений (например, значения используются для одного из многих способов сериализации перечисления) или если значения зависят от конфигурации или даже являются динамическими (например, если они были ценами напункт).В этих случаях обычно лучше всего отображать это отображение в EnumMap или Map.

3 голосов
/ 16 марта 2012
public enum ReadType {
    KWH(1300),
    Diagnostic(1100),
    ReadType3(1400, 1401);

    private int[] timTagNumbers;

    private ReadType(int ... numbers) {
        this.timTagNumbers = numbers;
    }

    public int[] getTimTagNumbers() {
        return timTagNumbers;
    }

    public static ReadType forTimTagNumber(int n) {
        for (ReadType type : values()) {
            if (Arrays.binarySearch(type.timTagNumbers, n) != -1) {
                return type;
            }
        }

        throw new NoSucheElementException();  // if not found
    }

С этим вы можете сделать

int[] timTagNumbers = ReadType.Diagnostic.getTimTagNumbers();  // [ 1100 ]

и

ReadType type3 = ReadType.forTimTagNumber(1401);  // ReadType.ReadType3
0 голосов
/ 16 марта 2012

Если вы можете наложить некоторые ограничения, например, не более 2 тегов могут быть связаны с типом чтения, и каждый тег не больше 2 ^ 15, тогда вы можете сохранить два числа в 1 целое число.См. этот пост S / O для более подробной информации.

0 голосов
/ 16 марта 2012

Вы можете сделать что-то вроде следующего: когда вы вводите значения в скобках, где объявлена ​​переменная enum, она вызывает конструктор перечисления.Вам нужно создать другой метод в самом перечислении, чтобы получить тип перечисления из целочисленного значения.Смотри ниже.

public enum ReadType {
        KWH(), DIAGNOSTIC(), READTYPE3();

        public ReadType getReadType(int num) {
            ReadType toReturn = KWH;
            switch (num) {
            case 1300:
                toReturn = KWH;
                break;
            case 1100:
                toReturn = DIAGNOSTIC;
                break;
            case 1400:
                toReturn = READTYPE3;
                break;
            case 1401:
                toReturn = READTYPE3;
                break;
            }
            return toReturn;

        }
0 голосов
/ 16 марта 2012

Вы действительно можете использовать перечисления таким образом, но в вашем примере отсутствует личное поле и конструктор.

Что-то вроде:

public enum Bla{
    CASE1(100),CASE2(200);

    private int amount;

    private Bla(int amount) {
        this.amount = amount;
    }

    public Bla getByValue(int value){
        switch (value) {
            case 100: return CASE1;
            case 200: return CASE2;
        }
        return null;
    }

}

Я включил «обратный поиск»"метод, который возвращает Enum с заданным значением.

Основным преимуществом является то, что вы можете использовать оставшуюся часть кода, используя" Bla "вместо int, что гарантирует безопасность типов в ваших операциях, в основном, это 'сделает невозможным передачу недопустимого значения int в качестве параметра метода (и вы можете использовать операторы switch над перечислениями, и это довольно здорово в некоторых сценариях использования).

РЕДАКТИРОВАТЬ: я заметил после того, как я написал, что вам нужноболее одного int для указания Enum, но применяется та же логика, конечно, с должными изменениями в методах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...