Получение перечисления, связанного со значением int



ранее у меня были свои перечисления LegNo, определенные просто как:



NO_LEG, LEG_ONE, LEG_TWO


и return LegNo.values()[i];, я смог получить значение, связанное с каждым перечислением.



но теперь я решил, что хочу LegNo перечисление NO_LEG быть int -1 вместо 0
поэтому я решил использовать частный конструктор для инициализации и установки его значения int



NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

private LegNo(final int leg) { legNo = leg; }


только сейчас, потому что я делаю это таким образом values() метод не будет работать для NO_LEG перечисление. Как получаю ли я перечисление, связанное с int? Есть ли какой-либо эффективный способ сделать это, кроме использования оператора case switch или if-elseif-elseif



Я вижу много вопросов SO, связанных с получением значения int из перечисления, но я после обратного.

610   8  

8 ответов:

редактировать август 2018

сегодня я бы реализовал это следующим образом

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private final int value;

    LegNo(int value) {
        this.value = value;
    }

    public static Optional<LegNo> valueOf(int value) {
        return Arrays.stream(values())
            .filter(legNo -> legNo.value == value)
            .findFirst();
    }
}

вам придется поддерживать отображение внутри перечисления.

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private int legNo;

    private static Map<Integer, LegNo> map = new HashMap<Integer, LegNo>();

    static {
        for (LegNo legEnum : LegNo.values()) {
            map.put(legEnum.legNo, legEnum);
        }
    }

    private LegNo(final int leg) { legNo = leg; }

    public static LegNo valueOf(int legNo) {
        return map.get(legNo);
    }
}

статический блок будет вызван только один раз, поэтому здесь практически нет проблем с производительностью.

изменить: переименовал метод в valueOf поскольку он более встроен в другие классы Java.

вы также можете включить статический метод в перечисление, которое перебирает все члены и возвращает правильный.

public enum LegNo {
   NO_LEG(-1),
   LEG_ONE(1),
   LEG_TWO(2);

   private int legIndex;

   private LegNo(int legIndex) { this.legIndex = legIndex; }

   public static LegNo getLeg(int legIndex) {
      for (LegNo l : LegNo.values()) {
          if (l.legIndex == legIndex) return l;
      }
      throw new IllegalArgumentException("Leg not found. Amputated?");
   }
}

теперь, если вы хотите получить значение перечисления целым числом, вы просто используете:

int myLegIndex = 1; //expected : LEG_ONE
LegNo myLeg = LegNo.getLeg(myLegIndex);

adarshr это адаптирован к Java 8:

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;

import java.util.Map;

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private final int legNo;

    private final static Map<Integer, LegNo> map =
            stream(LegNo.values()).collect(toMap(leg -> leg.legNo, leg -> leg));

    private LegNo(final int leg) {
        legNo = leg;
    }

    public static LegNo valueOf(int legNo) {
        return map.get(legNo);
    }
}

вы также можете получить доступ к значению Enum, соответствующему заданному целочисленному значению, просто вызвав метод values () на enum LegNo. Он возвращает поле перечислений LegNo: LegNo.values[0]; //returns LEG_NO LegNo.values[1]; //returns LEG_ONE LegNo.values[2]; //returns LEG_TWO

Не совсем то, что он искал, но довольно близко, хотя и очень просто. (Хотя субъект мертв, это может быть полезно для кого-то еще.)

Java 8 способ со значением по умолчанию:

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private final int legNo;

    LegNo(int legNo) {
        this.legNo = legNo;
    }

    public static LegNo find(int legNo, Supplier<? extends LegNo> byDef) {
        return Arrays.asList(LegNo.values()).stream()
                .filter(e -> e.legNo == legNo).findFirst().orElseGet(byDef);
    }
}

звоните:

LegNo res = LegNo.find(0, () -> LegNo.NO_LEG);

или за исключением:

LegNo res = LegNo.find(0, () -> {
    throw new RuntimeException("No found");
});

Так как ваше перечисление содержит только 3 элемента, самый быстрый способ будет просто использовать серию if else, Как вы предложили.

edit: ответ, который предоставил adarshr, лучше подходит для общих случаев, где есть много значений перечисления, но я думаю, что это перебор для вашей проблемы.

public enum LegNo {
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);

    private int legNo;

    private LegNo(int leg) { legNo = leg; }

    public static LegNo valueOf(int legNo) {
        for (LegNo leg : LegNo.values()) {
            if (leg.legNo == legNo) return leg;
        }   
    }
}

assert LegNo.valueOf(2) == LegNo.LEG_TWO
assert LegNo.valueOf(3) == null
public enum body
{
    NO_LEG = 0,         // bit 1
    LEG_ONE = 2,        // bit 2 
    LEG_TWO = 4,        // bit 3 
    NO_ARM = 8,          // bit 4 
    ARM_ONE = 16,  // bit 5 
    ARM_TWO = 32  // bit 6 

}

используйте его так (int)тело.LEG_ONE; / / / который возвращает 2

это также очень быстро и легко читается, так как это делается во время компиляции.

Comments

    Ничего не найдено.