Установка перечисления с использованием int, специфичного для этого перечисления?

Эй, все. Поэтому у меня есть набор перечислений и db с целыми числами, соответствующими этим перечислениям. Что-то вроде этого, например:

public static enum Day {
    SUNDAY(1), MONDAY(2), TUESDAY(3), WEDNESDAY(4), THURSDAY(5), FRIDAY(6), SATURDAY(7);

    public final int fId;

    private Day(int id) {
        this.fId = id;
    }
}

У меня также есть база данных, которая относится только к этим дням целыми числами, которые соответствуют их int в перечислении, указанном выше. То, что я хочу сделать, - это запросить базу данных, которая вернет целое число, а затем установите перечислитель для объекта на основе этого целого числа, возвращаемого из db. Я мог бы сделать что-то вроде этого:

public static Day getDay(int i) {
    switch(i) {
    case 1:
        return Day.SUNDAY;
    case 2: 
        return Day.MONDAY;
    //And so on
    }
}

Но для набора перечислений с более чем 100 перечислениями внутри этого не представляется очень практичным.

Так есть способ сделать это? Снова моя цель - просто вставить значение int и вернуть счетчик, не создавая новый метод для многих перечислений в этом наборе. Возможно, я должен просто сделать это своим классом, а не перечислителем, но я надеялся сделать это таким образом. Спасибо!

Ответы

Ответ 1

У перечислений есть встроенный идентификационный номер, "порядковый номер", который вы можете использовать для этой цели, если у вас есть простой способ получить от числа, которое представляет заданное значение в базе данных, в порядковый номер перечисление. Ординалы назначаются значениям перечисления в том порядке, в котором они объявлены в исходном файле, начиная с 0, поэтому в вашем примере SUNDAY будет иметь порядковый номер 0, MONDAY из 1 и т.д.

Чтобы использовать это, вам просто нужно преобразовать целое число, хранящееся в базе данных, в соответствующий порядковый номер, а затем использовать его для для доступа к значению перечисления. Итак, для вашего примера реализация может быть

private static Day[] values = Day.values();
public static Day getDay(int i) {
    return values[i - 1];
}

Если порядок значений перечисления в соответствии с их идентификаторами базы данных является тем же самым порядком, в котором они объявлены в исходном коде, тогда вы можете в значительной степени использовать вышеуказанный метод as-is (за исключением изменения имени класса), В противном случае вам может понадобиться сделать что-то более сложное, чтобы сопоставить значения базы данных с ординалами; возможно, настроив массив, если отображение сильно нелинейно.

P.S. И, конечно, если вы это сделаете, не было бы пользы для поля fId.

Ответ 2

Вот простая реализация, которая будет работать:

public static enum Day {
    SUNDAY(1), MONDAY(2), TUESDAY(3), WEDNESDAY(4), THURSDAY(5), FRIDAY(6), SATURDAY(7);

    public final int fId;

    private Day(int id) {
        this.fId = id;
    }

    public static Day forInt(int id) {
        for (Day day : values()) {
            if (day.fId == id) {
                return day;
            }
        }
        throw new IllegalArgumentException("Invalid Day id: " + id);
    }
}

Если вы знаете, что ваши перечисления начинаются с 1, вы можете просто использовать это вместо:

public static Day forInt(int id) {
    return values()[id - 1];
}

Ответ 3

Класс перечисления должен иметь карту поиска, встроенную внутри как статическую переменную. Следовательно, ваш класс enum должен быть чем-то вроде.

public static enum Day {
    SUNDAY(1), MONDAY(2), TUESDAY(3), WEDNESDAY(4), THURSDAY(5), FRIDAY(6), SATURDAY(7);

    public final int fId;

    private Day(int id) {
        this.fId = id;
    }


   private static final Map<Integer, Day > lookup
   = new HashMap<Integer, Day >();

   static {
   for (Day s : EnumSet.allOf(Day.class))
         lookup.put(s.getIntValue(), s);
   }

   public static Day getValue(int intValue) {
      return lookup.get(intValue);
   }

}

Затем, чтобы получить правильное перечисление на основе int i, вы можете просто вызвать

Day.getValue(i);

Этот подход будет работать, даже если нумерация нелинейна или имеет пробелы.

Ответ 4

Отредактированный - кэш создан ленивым.

Вы можете создать рабочую среду Map<Integer,Day> и использовать ее в реализации getDay.

public static enum Day {
    SUNDAY(1), MONDAY(2), TUESDAY(3), WEDNESDAY(4), THURSDAY(5), FRIDAY(6), SATURDAY(7);

    private static Map<Integer,Day> CACHE = null;

    private static void lazyFillCache() {
        if (CACHE != null) return;

        final Map<Integer,Day> c = new HashMap<Integer,Day>();
        for (final Day d : Day.values()) {
            c.put(d.fId, d);
        }

        CACHE = c;
    }

    public static Day getDay(int i) {
        lazyFillCache();
        return CACHE.get(i);
    }

    public final int fId;

    private Day(int id) {
        this.fId = id;
    }
}

Изменить - Вдохновленный комментатором Tom Hawtins здесь, вы также можете использовать эту реализацию, которая использует возможности загрузки классов Java:

public static enum Day {
    SUNDAY(1), MONDAY(2), TUESDAY(3), WEDNESDAY(4), THURSDAY(5), FRIDAY(6), SATURDAY(7);

    private static class Cache {
        private static Map<Integer,Day> CACHE = new HashMap<Integer,Day>();

        static {
            for (final Day d : Day.values()) {
                CACHE.put(d.fId, d);
            }
        }
    }

    public static Day getDay(int i) {
        return Cache.CACHE.get(i);
    }

    public final int fId;

    private Day(int id) {
        this.fId = id;
    }
}

Ответ 5

Day.values ​​() вернет массив с нулевым значением значений перечисления.

Ответ 6

Day myDay = Day.values ​​() [x] - x - значение int