Wie erhalte ich einen Enum-Wert aus dem Index in Java?

Lesezeit: 5 Minuten

Ich habe eine Aufzählung in Java:

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

Ich möchte auf Enum-Werte per Index zugreifen, z

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

Wie soll ich das machen?

  • In der Informatik beginnen Indizes bei 0, nicht bei 1 😉

    – fredoverflow

    14. Juli 2011 um 11:59 Uhr


  • Bist du sicher, dass du willst? Im Allgemeinen sollten Sie die Ordnungszahl nicht berühren, außer wenn Sie Datenstrukturen auf niedriger Ebene implementieren (und dann alternative Mechanismen wie Namen für die Persistenz verwenden).

    – Tom Hawtin – Angelleine

    14. Juli 2011 um 12:20 Uhr

  • Sie hätten auch die Konstanten in der Klasse java.util.Calendar verwenden können. Sie sind von Januar bis Dezember von 0 bis 11 nummeriert. Achten Sie auf 12, da dies UnDezember ist (etwas, das mit dem Mondkalender zu tun hat). Aber ich bin nur neugierig, warum das Rad der Monatskonstanten neu erfunden werden soll, das bereits in der JRE “vorrätig” ist?

    – Chris Aldrich

    14. Juli 2011 um 12:47 Uhr

  • 2FredOverflow: Stimmt, ich habe die falsche Indizierung verwendet. 2Tom Hawtin: Ja, da bin ich mir sicher. Ich behalte Daten mit einem Framework bei und bekomme einen Integer-Index zurück, nicht die Aufzählung. 2Chris Aldrich: Dies ist nur ein Dummy-Beispiel, das nicht mit dem realen Fall übereinstimmt.

    – jk_

    14. Juli 2011 um 14:02 Uhr


  • Übrigens kommt Java 8 und höher mit a Month Aufzählung eingebaut.

    – Basilikum Bourque

    10. April 2019 um 20:22 Uhr


Versuche dies

Months.values()[index]

  • Beachten Sie, dass jedes Mal eine Kopie des Werte-Arrays geklont wird. Wenn Sie dies also in der inneren Schleife des leistungsempfindlichen Codes aufrufen, möchten Sie möglicherweise eine statische Kopie erstellen und diese verwenden.

    – Christoph Barbier

    4. Oktober 2013 um 0:11 Uhr

  • Ich bin verwirrt, warum sollte ich dann nicht stattdessen ein Array verwenden wollen?

    – Anudeep Samaiya

    21. September 2015 um 15:23 Uhr

  • @AnudeepSamaiya Möglicherweise möchten wir anstelle von Monaten die richtigen Enum-Konstanten (Months.JAN) im Code verwenden[1] überall, überallhin, allerorts.

    – Harry Freude

    22. September 2015 um 4:53 Uhr

  • @Christopher Barber hier ist ein Einzeiler zum “Erstellen einer statischen Kopie”: public static final ArrayList<Months> ALL = new ArrayList<Month>() {{ for (Months m : Months.values()) add(m); }};dann können Sie mit auf die Elemente zugreifen Months i = ALL.get(index)

    – muelleth

    31. August 2016 um 8:11 Uhr


  • Es wäre einfacher, einfach Months.values().clone() zu verwenden oder, wenn Sie wegen der Veränderlichkeit paranoid sind, es in eine unveränderliche Liste zu packen (siehe Sammlungen).

    – Christoph Barbier

    31. August 2016 um 20:16 Uhr

Hier sind drei Möglichkeiten, dies zu tun.

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

}

  • public static änderbar (sowohl Array als auch Nicht-final). Euw. Und ein IllegalArgumentException würde viel mehr Sinn machen, als a zurückzugeben null Bombe.

    – Tom Hawtin – Angelleine

    14. Juli 2011 um 12:24 Uhr

Benutzer-Avatar
Blauspecht

Ich habe es gerade versucht und bin auf folgende Lösung gekommen:

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

Die Klasse hat ihre eigenen Werte, die in einem Array gespeichert sind, und ich verwende das Array, um die Aufzählung an Indexposition zu erhalten. Wie oben erwähnt, beginnen Arrays bei 0 zu zählen. Wenn Sie möchten, dass Ihr Index bei ‘1’ beginnt, ändern Sie einfach diese beiden Methoden in:

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

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

In meinem Main bekomme ich das benötigte Länder-Objekt mit

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

Dadurch wird currCountry auf das letzte Land gesetzt, in diesem Fall Countries.KENTUCKY.

Denken Sie daran, dass dieser Code stark von ArrayOutOfBoundsExceptions betroffen ist, wenn Sie fest codierte Indizes verwenden, um Ihre Objekte abzurufen.

  • Sind Sie sicher, dass dies so funktioniert wie mit dem statischen Block? .values() liefert normalerweise einen Klon des internen (statischen) Arrays, nicht die bloße Referenz. Dieses Array ist vermutlich intern vorbelegt, sicher, aber es würde am Punkt von mit Nullen gefüllt werden static{} block (bevor das Objekt die Möglichkeit hatte, einen der Konstruktoren auszuführen). Ich könnte verwenden .values()aber nur beim ersten Anruf an get(index)wo es das Array für die spätere Indizierung wegstopft, oder jeden Wert inkrementell im Konstruktor füllen.

    – ein Leben

    27. April um 23:12 Uhr

Benutzer-Avatar
Mirko Brandt

Ich hatte kürzlich das gleiche Problem und habe die Lösung von Harry Joy verwendet. Diese Lösung funktioniert jedoch nur mit nullbasierter Aufzählung. Ich würde es auch nicht als sicher betrachten, da es sich nicht um Indizes handelt, die außerhalb des Bereichs liegen.

Die Lösung, die ich letztendlich verwendet habe, ist vielleicht nicht so einfach, aber sie ist absolut sicher und beeinträchtigt die Leistung Ihres Codes auch bei großen Aufzählungen nicht:

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

Wenn Sie sicher sind, dass Sie mit Ihrem Index niemals außerhalb der Reichweite liegen und Sie nicht verwenden möchten UNKNOWN wie ich es oben getan habe, kannst du natürlich auch tun:

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

1299500cookie-checkWie erhalte ich einen Enum-Wert aus dem Index in Java?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy