2011-09-05 101 views
1

如果我有一個對象約枚舉問題

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

和ID和名稱都已經提前確定,例如

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或名稱查找名稱或ID喜歡

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" 
+0

+1代碼的好解釋。 – amod

回答

1

這應做到:

Genre.ACTION.getId() 

如果你需要在運行時做到這一點:

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

謝謝!但是如果我一開始不瞭解流派。例如,我只得到一個字符串「行動」,我怎麼能把它變成Genre.Action? – cht

+0

這就是'valueOf'的作用(你應該使該字符串的名稱與該字符串的名稱相同,而不是一個大寫和一個小寫) – Thilo

+0

因此,如果我想要的實際值不是「ACTION」,而是其他語言中的「ACTION」像中國人,這種方式不推薦? – cht

2

嘗試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()等。

+1

您假定名稱字段與枚舉名稱有某種關係。 –

+0

@Adriaan是的,至少從發佈的源代碼看起來如此,尤其是。因爲枚舉版本沒有構造函數的名稱參數。 – Thomas

2

您可以通過調用Genre.ACTION來獲得其ID。的getId();

0

你爲什麼不使用枚舉構造與ID和字符串:

public enum Genre { 
    ACTION(1, "action"), HORROR(2, "horror"); 
} 
0
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

如果您需要通過它的名稱來訪問特定的元素,你需要做的是這樣:

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

但是,如果你需要經常這樣做,在更動態的方式,我建議建立普通班,並保持所有數據在一些Map<String, Movie>容器。

+0

對不起,我的JAVA和英語。 「將所有數據保存在Map 」中意味着什麼? – cht

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

是一個簡單的方法來做到這一點。 但如果你需要更經常地做,我會建議你創建你自己的類,並使用MAP<-"-,-"->作爲邁克爾說。

編輯:----

至於你說的很少能改變用這種方式 - >

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

謝謝!你的意思是,如果我需要改變流派,就像添加或刪除流派一樣。那麼,我創造了對象爲行動和恐怖更好? – cht

+0

是的,因爲枚舉應該被引用爲常量。這些值很少會改變。爲了經常改變價值,你爲什麼不喜歡上課?其全部符合您的要求。最近我也遇到了同樣的問題,我的名字和id是不變的,只有少數名字像你一樣有HORROR,ACTION我使用了類,但後來我發現了一個更好的方法,用enum做。如果他們很少會改變爲枚舉。告訴我是否需要任何代碼會編輯我的答案。 – amod

+0

我認爲在我的情況下,它很少改變。但我仍然想知道如果經常改變它,該怎麼做。如果我經常改變它,我怎麼寫呢?因爲如果我創建一個對象操作,並給它的ID和名稱。我如何才能使用String「action」來獲取Object Action?謝謝! – cht

3

如果你堅持要用一個枚舉這一點,你可以使用現有的枚舉設施。下面的解決方案假定枚舉名稱和順序可以代替你的名字和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 

另一種合適的方法是使用地圖的查詢,像米哈爾Š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->的名字並寫了一個單獨的方法(getGenreIdByName)做反向查找名稱 - > ID。你可以扭轉,或者使用第二個地圖,使這兩個查詢快(在需要保持一個額外的地圖的費用)。

我選擇存儲在地圖中的ID和名稱。你也可以使用Genre類本身作爲地圖值。這將允許您稍後添加額外的字段(如'description')。

如果你需要,你代表在不同的語言風格,你可以用把ResourceBundle本地化輸出。在你的類路徑根目錄下創建一個語言文件。

在文件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'的文件),該包可以在找不到使用的Locale的包的情況下自動使用。

+0

謝謝!這真的很有用,我需要一些時間來消費! – cht

+0

'如果你堅持使用枚舉來實現這個......' - 如果流派的數量是固定的,那麼我更喜歡enum版本,即在運行時可能不會改變。 – Thomas

+0

@Thomas我不認爲這是主要標準。如果你需要引用很多不同的流派(比如你的代碼中有Genre.ACTION等),我會使用枚舉。但是,如果這被用於Web應用程序中,並且ID /名稱被動態地傳遞到/從前端/持久層,那麼我認爲像地圖這樣的緩存查找更有意義。最重要的是,像電影類型這樣的數據在我的經驗中幾乎沒有變化。作爲一種預防措施,我會將其建模爲一個持久實體,以避免爲每次更改流派重新部署我的應用程序。 –