Как сопоставить значение обратно с перечислением?

Для перечисления, где каждый экземпляр связан с некоторым значением:

public enum SQLState
{
  SUCCESSFUL_COMPLETION("00000"),
  WARNING("01000");

  private final String code;
  SQLState(String code)
  {
    this.code = code;
  }
}

Как я могу построить карту для эффективного обратного просмотра? Я попробовал следующее:

public enum SQLState
{
  SUCCESSFUL_COMPLETION("00000"),
  WARNING("01000");

  private final String code;
  private static final Map<String, SQLState> codeToValue = Maps.newHashMap();
  SQLState(String code)
  {
    this.code = code;
    codeToValue.put(code, this); // problematic line
  }
}

но Java жалуется: Illegal reference to static field from initializer. То есть статическая карта инициализируется после всех значений перечисления, поэтому вы не можете ссылаться на нее из конструктора. Любые идеи?

Ответ 1

использование:

static {
  for (SQLState sqlState : values()){
     codeToValue.put(sqlState.code, sqlState);
  }
}

Ответ 2

Когда вы используете Guava, я рекомендую использовать следующий код:

public enum SQLState {

    SUCCESSFUL_COMPLETION("00000"),
    WARNING("01000"),
    ;

    private final String code;
    private SQLState(String code) {
        this.code = code;
    }

    public static final Function<SQLState,String> EXTRACT_CODE = new Function<SQLState,String>() {
        @Override
        public String apply(SQLState input) {
            return input.code;
        }
    };

    public static final Map<String, SQLState> CODE_TO_VALUE = ImmutableMap.copyOf( Maps.uniqueIndex(EnumSet.allOf(SQLState.class), EXTRACT_CODE) );

    public static void main(String[] args) {
        System.out.println( SQLState.CODE_TO_VALUE.get("00000") );
    }

}

Это производит как ожидалось: "SUCCESSFUL_COMPLETION"

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

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

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


Проверьте Документация MapsInIndex, которая является действительно классной функцией Guava, которая позволяет индексировать любой объект по любому из его атрибутов. В случае, если многие объекты используют одно и то же значение атрибута, вы можете использовать Multimaps.index, который для каждого ключа предоставит вам список объектов, имеющих этот атрибут.

Ответ 3

Инициализировать статическую карту в статическом {...} блоке перед конструктором. Посмотрите на статические блоки инициализатора.