Вопросы по enum - PullRequest
       3

Вопросы по enum

1 голос
/ 05 сентября 2011

Если у меня есть объект

public class Genre {
    private int id;
    private int name;
}

И идентификатор и имя были определены заранее, например

if (id == 1)
    name = "action";
else if (id == 2)
    name = "horror";

Моя проблема в том, как хорошо создать эти два метода

Genre.getName(1); // return "action";
Genre.getId("action"); // return 1;

Я подумал, может быть, я смогу использовать enum, например

public enum Genre {
    ACTION(1), HORROR(2);

    private final int id;
    private final String name;

    private Genre(int id) {
        this.id = id;
        this.name = getName(id);
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public static String getName(int i) {
        switch(i) {
        case 1 : return "action";
        case 2: return "horror";
        default :
            return null;
        }
    }
}

Но, таким образом, я понятия не имею, как

Genre.getId("action"); // return 1;

И я боюсь, что я использую enum не правильно. Не могли бы вы дать мне совет? Спасибо!
---
Сначала, что я хочу сделать, это в моем случае, я хочу использовать идентификатор или имя, чтобы найти имя или идентификатор, как

int id = 1;
Genre.getName(id); // return "action"

или

String name = "action";
Genre.getId(name); // return 1

А теперь спасибо за все советы, я понимаю, почему я хочу сделать это

int id = 1;
Genre.getGenre(id); // return Genre that id = 1 and the name = "action"

или

String name = "action";
Genre.getGenre(name); // return Genre that id = 1 and the name = "action"

Ответы [ 8 ]

3 голосов
/ 05 сентября 2011

Если вы настаиваете на использовании перечисления для этого, вы можете просто использовать существующие средства перечисления. В приведенном ниже решении предполагается, что вместо полей вашего имени и идентификатора могут использоваться имя перечисления и порядковый номер:

public enum Genre {

    // ordinal 0, name = "ACTION"
    ACTION,

    // ordinal 1, name = "HORROR"
    HORROR;
}

public static void main(String[] args) {

    int horrorOrdinal = 1;
    Genre horrorGenre = Genre.values()[horrorOrdinal];
    String horrorName = horrorGenre.name();

    String actionName = "ACTION";
    Genre actionGenre = Genre.valueOf(actionName);
    int actionOrdinal = actionGenre.ordinal();

    System.out.println(String.format("%s=%s %s=%s", horrorName, horrorOrdinal, actionName, actionOrdinal));
}

Выход:

HORROR=1 ACTION=0

Другим подходящим способом было бы использовать карту для поиска, как предложил Михаил Шрайер:

private static Map<Integer, String> genres = new HashMap<Integer, String>();

public static void main(String[] args) {

    initGenres();

    int horrorOrdinal = 2;
    String horrorName = genres.get(horrorOrdinal);

    String actionName = "action";
    int actionOrdinal = getGenreIdByName(actionName);

    System.out.println(String.format("%s=%s %s=%s", horrorName, horrorOrdinal, actionName, actionOrdinal));
}

private static void initGenres() {
    genres.put(1, "action");
    genres.put(2, "horror");
}

private static int getGenreIdByName(String genreName) {
    for (Entry<Integer, String> entry : genres.entrySet()) {
        if (entry.getValue().equals(genreName)) {
            return entry.getKey();
        }
    }
    throw new IllegalArgumentException("Genre not found: " + genreName);
}

Выход:

horror=2 action=1

Особенности проектирования:

В этом примере я решил использовать (быстрый) поиск по карте для id-> name и написал отдельный метод (getGenreIdByName) для выполнения обратного поиска name-> id. Вы можете изменить это или использовать вторую карту для ускорения обоих поисков (за счет необходимости поддерживать дополнительную карту).

Я решил сохранить идентификатор и имя на карте. Вы также можете использовать сам класс Genre в качестве значения карты. Это позволит вам позже легко добавить дополнительные поля (например, «описание»).

Если вам нужно представить свои жанры на разных языках, вы можете использовать ResourceBundles для локализации вывода. Создайте языковой файл в корне вашего пути к классам.

В файле genres_nl.properties:

horror=heel eng
action=actie

Где суффикс _nl в имени файла указывает на язык.

Тогда в вашем коде, в initGenres:

ResourceBundle genreNames = ResourceBundle.getBundle("genres", new Locale("nl");

А при получении названия жанра:

String horrorName = genreNames.getString(genres.get(horrorOrdinal));

Обратите внимание, что getString может выдать исключение MissingResourceException во время выполнения, если пакет не найден. Чтобы избежать этого, убедитесь, что вы создали пакет «по умолчанию» без суффикса (так что в этом случае файл с именем «genres.properties») автоматически используется в случае, если не удается найти пакет для используемого языкового стандарта.

2 голосов
/ 05 сентября 2011

Вы можете получить его идентификатор, вызвав Genre.ACTION.getId ();

2 голосов
/ 05 сентября 2011

Попробуйте метод valueOf(...):

void String getId(String name) {
  //names are upper case, so account for that
  //handling non-existent names is an excersize for you
  valueOf(name.toUpperCase()).getId(); 
}

Обратите внимание, что существуют лучшие методы (как предложил Тило), но если у вас есть только строка, вы можете использовать ее.

Редактировать: другое примечание:

В вашем методе getName(int i) вы можете захотеть вернуть ACTION.name() и т. Д., Чтобы повысить безопасность рефакторинга и использовать правильный регистр.

1 голос
/ 05 сентября 2011
ACTION(1, "action"), HORROR(2, "horror"); 

- это простой способ сделать это.Но если вам требуется делать это чаще, я бы предложил вам создать собственный класс и использовать MAP<-"-,-"->, как сказал micheal.

Редактировать: ----

Как вы сказали,редко меняются, используйте этот способ ->

    public enum Genre {
    ACTION(0, "action"), HORROR(1, "horror"), ROMANCE(2, "romance"), COMEDY(5, "comedy");
    public final int id;
    public final String name;

    private Genre(int id, String name) {
        this.id = id;
        this.name = name;
    };

    public final static int length = Genre.values().length;

    public static String[] getGenre() {
        String[] genreList = new String[length];
        int i = 0;

        for (Genre attribute : Genre.values()) {
            genreList[i++] = attribute.toString();
        }
        return genreList;
    }

    @Override
    public String toString() {
        return this.name;
    }
}

Пожалуйста, помните, используйте это как Genre.HORROR.id и обратите внимание, что использование этого способа лучше всего согласно вашему требованию.

1 голос
/ 05 сентября 2011

Это должно сделать это:

Genre.ACTION.getId()

А если вам нужно сделать это во время выполнения:

Genre.valueOf("ACTION").getId()
0 голосов
/ 05 сентября 2011

Если вам нужен доступ к определенному элементу по его имени, вам нужно сделать это следующим образом:

Genre.valueOf("ACTION").getId()

Однако, если вам нужно делать это часто и более динамично, я предлагаю создать обычный класс и хранить все данные в некотором контейнере Map<String, Movie>.

0 голосов
/ 05 сентября 2011
public enum Genre {
    ACTION(1, "action"), HORROR(2, "horror");

    private final int id;
    private final String name;

    private Genre(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}
0 голосов
/ 05 сентября 2011

Почему бы вам не использовать конструктор Enum с id и String:

public enum Genre {
    ACTION(1, "action"), HORROR(2, "horror");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...