关于枚举的问题

发布于 2024-12-02 23:42:33 字数 1521 浏览 2 评论 0原文

如果我有一个对象

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

并且 id 和 name 是预先确定的,例如

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

我的问题是如何很好地创建这两个方法

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

我想也许我可以使用枚举,就像

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;

并且我恐怕我使用枚举不正确。 你能给我一些建议吗?谢谢!
---
首先,我想做的是在我的情况下,我想使用 id 或 name 来查找名称或 id,例如

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

or

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"

If I have a Object

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

And the id and name were been determined in advance, for example

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

My problem is how to create these two methods well

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

I thought maybe I can use enum, like

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;
        }
    }
}

But in this way, I have no idea how to

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

And im afraid i use enum not correctly.
Could you give me some advice? Thanks!

---

At first, What I want to do this is in my case i want to use id or name to find the name or id like

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

or

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

And now thanks for all the advices, I realize why I want to do is

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

or

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

智商已欠费 2024-12-09 23:42:33

如果您坚持为此使用枚举,则可以使用现有的枚举工具。下面的解决方案假设可以使用枚举名称和序数来代替您的名称和 id 字段:

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

另一种合适的方法是使用映射进行查找,如 Michał Šrajer 建议的那样:

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。您可以相反,或者使用第二个映射来加快两次查找的速度(代价是需要维护额外的映射)。

我选择将 ID 和名称存储在地图中。您还可以使用 Genre 类本身作为地图值。这将允许您稍后轻松添加额外的字段(如“描述”)。

如果您需要用不同的语言来表示您的流派,您可以使用 ResourceBundles 来本地化输出。在类路径根目录中创建一个语言文件。

在文件类型_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”的文件),如果找不到所使用的区域设置的包,则会自动使用该包。

If you insist on using an enum for this, you can just use the existing enum facilities. The solution below assumes the enum name and ordinal may be used in place of your name and id fields:

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));
}

Output:

HORROR=1 ACTION=0

Another suitable way would be to use a map for the lookup, like Michał Šrajer suggested:

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);
}

Output:

horror=2 action=1

Design considerations:

In this example I chose to use the (fast) map lookup for id->name and wrote a seperate method (getGenreIdByName) to do the reverse lookup name->id. You could reverse that, or use a second map to make both lookups fast (at the cost of needing to maintain an extra map).

I chose to store the id and name in the map. You could also use the Genre class itself as the map value. This would allow you to easily add extra fields (like 'description') later on.

If you need to represent you genres in different languages, you can use ResourceBundles to localize the output. Create a language file in your classpath root.

In file genres_nl.properties:

horror=heel eng
action=actie

Where the _nl suffix in the filename indicates the language.

Then in your code, in initGenres:

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

And when getting the genre name:

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

Note that getString can throw the runtime exception MissingResourceException if the bundle is not found. To avoid this, make sure you create a 'default' bundle with no suffix (so in this case a file named 'genres.properties') which is automatically used in case no bundle for the used Locale can be found.

一抹苦笑 2024-12-09 23:42:33

尝试 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(); 
}

请注意,有更好的方法(如 Thilo 建议的),但如果您只有一个字符串,则可以使用它。

编辑:另一个注意事项:

在您的 getName(int i) 方法中,您可能希望返回 ACTION.name() 等,以便重构更加安全并使用正确的情况。

Try the valueOf(...) method:

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(); 
}

Note that there are better methods (like Thilo suggested), but if you have a string only, you might use that.

Edit: another note:

In your getName(int i) method, you might want to return ACTION.name() etc. in order to be more refactoring safe and use the correct case.

城歌 2024-12-09 23:42:33

您可以通过调用 Genre.ACTION.getId() 获取其 ID;

You can get its ID by calling Genre.ACTION.getId();

箜明 2024-12-09 23:42:33

这应该可以做到:

Genre.ACTION.getId()

如果您需要在运行时执行此操作:

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

This should do it:

Genre.ACTION.getId()

And if you need to do it at run-time:

Genre.valueOf("ACTION").getId()
请远离我 2024-12-09 23:42:33
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
另请注意,最好根据您的要求使用这种方式。

ACTION(1, "action"), HORROR(2, "horror"); 

is a easy way to do it.
But if you are require to do it more often i would suggest you to create your own class and use MAP<-"-,-"-> as micheal said.

Edit:----

As you said the rarely gonna change use this way-->

    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;
    }
}

Please remember use this as Genre.HORROR.id
also note that using this way is best as per your requirement.

┈┾☆殇 2024-12-09 23:42:33

为什么不使用带有 id 和 String 的 Enum 构造函数:

public enum Genre {
    ACTION(1, "action"), HORROR(2, "horror");
}

Why don't you use the Enum Constructor with id and String:

public enum Genre {
    ACTION(1, "action"), HORROR(2, "horror");
}
你是年少的欢喜 2024-12-09 23:42:33
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;
    }
}
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;
    }
}
终弃我 2024-12-09 23:42:33

如果您需要通过名称访问特定元素,则需要这样做:

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

但是,如果您需要经常以更动态的方式执行此操作,我建议创建常规类,并将所有数据保存在某个 < code>Map容器。

If you need to access particular element by it's name, you need to do it this way:

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

However, if you need to do it often, and in more dynamic way, I suggest to create regular class, and to keep all data in some Map<String, Movie> container.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文