Bagaimana cara mendapatkan Nilai Enum dari indeks di Jawa?

96

Saya memiliki enum di Java:

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

Saya ingin mengakses nilai enum dengan indeks, misalnya

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

Bagaimana saya melakukannya?

jk_
sumber
12
Dalam ilmu komputer, indeks dimulai dari 0, bukan 1 ;-)
fredoverflow
1
Anda yakin mau? Umumnya Anda tidak boleh menyentuh ordinal, selain menerapkan struktur data tingkat rendah (lalu, gunakan mekanisme alternatif, seperti nama, untuk persistensi).
Tom Hawtin - tackline
Anda juga bisa menggunakan konstanta di kelas java.util.Calendar. Mereka diberi nomor 0 - 11 untuk Jan - Des. Berhati-hatilah dengan 12 karena itu adalah UnDecember (ada hubungannya dengan kalender lunar). Tapi saya hanya ingin tahu mengapa menciptakan kembali konstanta bulan yang sudah menjadi "stok" di JRE?
Chris Aldrich
2FredOverflow: Setuju, saya menggunakan pengindeksan yang salah. 2Tom Hawtin: Ya, saya yakin. Saya mempertahankan data dengan beberapa kerangka kerja dan saya mendapatkan kembali indeks integer, bukan enum. 2Chris Aldrich: Ini hanya contoh dummy yang tidak sesuai dengan kasus sebenarnya.
jk_
Omong-omong, Java 8 dan yang lebih baru hadir dengan Monthenum built-in.
Basil Bourque

Jawaban:

229

Coba ini

Months.values()[index]
Harry Joy
sumber
37
Perhatikan itu akan mengkloning salinan larik nilai setiap kali, jadi jika Anda memanggil ini di loop dalam kode sensitif kinerja, Anda mungkin ingin membuat salinan statis dan menggunakannya.
Christopher Barber
1
Saya bingung, lalu mengapa saya tidak ingin menggunakan array?
Anudeep Samaiya
@AnudeepSamaiya mungkin kita ingin menggunakan konstanta enum yang tepat (Months.JAN) dalam kode daripada bulan [1] di mana-mana.
Harry Joy
@Christopher Barber inilah satu baris untuk "membuat salinan statis" public static final ArrayList<Months> ALL = new ArrayList<Month>() {{ for (Months m : Months.values()) add(m); }};Months i = ALL.get(index)
:,
Akan lebih mudah untuk hanya menggunakan Months.values ​​(). Clone () atau jika Anda paranoid tentang mutabilitas untuk membungkusnya dalam daftar yang tidak dapat diubah (lihat Koleksi)
Christopher Barber
20

Berikut tiga cara untuk melakukannya.

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

}
Trever Shick
sumber
5
public staticbisa berubah (baik array dan non- final). Euw. Dan IllegalArgumentExceptionakan lebih masuk akal daripada mengembalikan nullbom.
Tom Hawtin - tackline
2

Saya baru saja mencoba hal yang sama dan menemukan solusi berikut:

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

Kelas memiliki nilai sendiri yang disimpan di dalam array, dan saya menggunakan array untuk mendapatkan enum di indexposition. Seperti disebutkan di atas, array mulai dihitung dari 0, jika Anda ingin indeks Anda mulai dari '1' cukup ubah kedua metode ini menjadi:

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

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

Di dalam Utama saya, saya mendapatkan objek negara yang dibutuhkan

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

yang menyetel currCountry ke negara terakhir, dalam hal ini Countries.KENTUCKY.

Ingat saja kode ini sangat dipengaruhi oleh ArrayOutOfBoundsExceptions jika Anda menggunakan indikasi hardcode untuk mendapatkan objek Anda.

Blauspecht
sumber
1

Saya baru-baru ini mengalami masalah yang sama dan menggunakan solusi yang diberikan oleh Harry Joy. Solusi itu hanya bekerja dengan enumaration berbasis nol. Saya juga tidak akan menganggapnya aman karena tidak berurusan dengan indeks yang berada di luar jangkauan.

Solusi yang akhirnya saya gunakan mungkin tidak sesederhana itu tetapi sepenuhnya aman dan tidak akan merusak kinerja kode Anda bahkan dengan enum besar:

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

Jika Anda yakin bahwa Anda tidak akan pernah berada di luar jangkauan dengan indeks Anda dan Anda tidak ingin menggunakan UNKNOWNseperti yang saya lakukan di atas, Anda tentu saja dapat melakukannya:

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