如何从 Java 中的索引获取枚举值?

我在 Java 中有一个 enum:

public enum Months
{
JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
}

我想通过索引访问枚举值,例如。

Months(1) = JAN;
Months(2) = FEB;
...

我该怎么做?

186995 次浏览

Try this

Months.values()[index]

Here's three ways to do it.

public enum Months {
JAN(1), FEB(2), MAR(3), APR(4), MAY(5), JUN(6), JUL(7), AUG(8), SEP(9), OCT(10), NOV(11), DEC(12);




int monthOrdinal = 0;


Months(int ord) {
this.monthOrdinal = ord;
}


public static Months byOrdinal2ndWay(int ord) {
return Months.values()[ord-1]; // less safe
}


public static Months byOrdinal(int ord) {
for (Months m : Months.values()) {
if (m.monthOrdinal == ord) {
return m;
}
}
return null;
}
public static Months[] MONTHS_INDEXED = new Months[] { null, JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };


}








import static junit.framework.Assert.assertEquals;


import org.junit.Test;


public class MonthsTest {


@Test
public void test_indexed_access() {
assertEquals(Months.MONTHS_INDEXED[1], Months.JAN);
assertEquals(Months.MONTHS_INDEXED[2], Months.FEB);


assertEquals(Months.byOrdinal(1), Months.JAN);
assertEquals(Months.byOrdinal(2), Months.FEB);




assertEquals(Months.byOrdinal2ndWay(1), Months.JAN);
assertEquals(Months.byOrdinal2ndWay(2), Months.FEB);
}


}

I just tried the same and came up with following solution:

public enum Countries {
TEXAS,
FLORIDA,
OKLAHOMA,
KENTUCKY;


private static Countries[] list = Countries.values();


public static Countries getCountry(int i) {
return list[i];
}


public static int listGetLastIndex() {
return list.length - 1;
}
}

The class has it's own values saved inside an array, and I use the array to get the enum at indexposition. As mentioned above arrays begin to count from 0, if you want your index to start from '1' simply change these two methods to:

public static String getCountry(int i) {
return list[(i - 1)];
}


public static int listGetLastIndex() {
return list.length;
}

Inside my Main I get the needed countries-object with

public static void main(String[] args) {
int i = Countries.listGetLastIndex();
Countries currCountry = Countries.getCountry(i);
}

which sets currCountry to the last country, in this case Countries.KENTUCKY.

Just remember this code is very affected by ArrayOutOfBoundsExceptions if you're using hardcoded indicies to get your objects.

I recently had the same problem and used the solution provided by Harry Joy. That solution only works with with zero-based enumaration though. I also wouldn't consider it save as it doesn't deal with indexes that are out of range.

The solution I ended up using might not be as simple but it's completely save and won't hurt the performance of your code even with big enums:

public enum Example {


UNKNOWN(0, "unknown"), ENUM1(1, "enum1"), ENUM2(2, "enum2"), ENUM3(3, "enum3");


private static HashMap<Integer, Example> enumById = new HashMap<>();
static {
Arrays.stream(values()).forEach(e -> enumById.put(e.getId(), e));
}


public static Example getById(int id) {
return enumById.getOrDefault(id, UNKNOWN);
}


private int id;
private String description;


private Example(int id, String description) {
this.id = id;
this.description= description;
}


public String getDescription() {
return description;
}


public int getId() {
return id;
}
}

If you are sure that you will never be out of range with your index and you don't want to use UNKNOWN like I did above you can of course also do:

public static Example getById(int id) {
return enumById.get(id);
}