如何使用id检索枚举名称?

时间:2013-03-13 08:29:05

标签: java enums

我有enum

public enum EnumStatus {

    PASSED(40L, "Has Passed"),
    AVERAGE(60L, "Has Average Marks"),
    GOOD(80L, "Has Good Marks");

    private java.lang.String name;

    private java.lang.Long id;

    EnumStatus(Long id, java.lang.String name) {
        this.name = name;
        this.id = id;
    }

    public java.lang.String getName() {
        return name;
    }

    public java.lang.Long getId() {
        return id;
    }
}

我必须使用ID(40,60,80)来获取枚举名称(PASSEDAVERAGEGOOD)。我该怎么做?

11 个答案:

答案 0 :(得分:52)

enum中创建一个静态方法,搜索values(隐式方法/成员,不确切知道它是哪个)并返回相应的值。对于方法无法找到匹配值的情况,您应该创建一个特殊条目,例如UNKNOWN,您可以返回。这样,您就不必返回null,这总是一个坏主意。

public static EnumStatus getById(Long id) {
    for(EnumStatus e : values()) {
        if(e.id.equals(id)) return e;
    }
    return UNKNOWN;
}

顺便说一下 - 你的代码似乎错了。 GOOD之后的括号似乎不属于那里。

答案 1 :(得分:11)

这可以使用静态地图和静态初始化程序来完成:

public enum EnumStatus {

    PASSED(40L, "Has Passed"),
    AVERAGE(60L, "Has Average Marks"),
    GOOD(80L, "Has Good Marks");

    private static final Map<Long, EnumStatus> byId = new HashMap<Long, EnumStatus>();
    static {
        for (EnumStatus e : EnumStatus.values()) {
            if (byId.put(e.getId(), e) != null) {
                throw new IllegalArgumentException("duplicate id: " + e.getId());
            }
        }
    }

    public static EnumStatus getById(Long id) {
        return byId.get(id);
    }

    // original code follows

    private java.lang.String name;

    private java.lang.Long id;

    EnumStatus(Long id, java.lang.String name) {
        this.name = name;
        this.id = id;
    }

    public java.lang.String getName() {
        return name;
    }

    public java.lang.Long getId() {
        return id;
    }

}

这将提供O(1) getById()方法,并会自动检测您是否意外地在枚举中出现重复ID。

答案 2 :(得分:3)

您按照以下方式开展此工作:

public static String fromId(long id) {
        for (EnumStatus es : EnumStatus.values()) {
            if (es.id.equals(id)) {
                return es.getName();
            }
        }
        throw new IllegalArgumentException();
}

答案 3 :(得分:1)

Enum中添加一个方法,然后通过传递ID来获取它。

 public static ArrayList<EnumStatus> getEnumStatusById(ArrayList<Long> idList) {
    ArrayList<EnumStatus> listById = new ArrayList();
    for(EnumStatus es: EnumStatus.values()) {
        if( idList.contains(es.getId())) {
            listById.add(es);
        }
    }
    return listById;
}

答案 4 :(得分:1)

public static EnumStatus getById(long id)
{
  for (EnumStatus e : EnumStatus.values())
  {
    if (id == e.getId()) return e;
  } 
  throw new IllegalArgumentException("oh no");
}

答案 5 :(得分:0)

迭代所有值并比较Id

for (EnumStatus  enumStatus : EnumStatus.values()) {
   if (..) {..}
}

答案 6 :(得分:0)

有时enum的序数与这种id有明确的关系,能够以一种巧妙的方式在这些方法中获得O(1)。在您的代码中,很明显

EnumStatus.X = 40 + 20 * ordinal

因此您可以利用static array that is generated under the hoods

public static EnumStatus fromId(Long id) {
    int index = (id - 40L) / 20L;
    return values()[index];
}

答案 7 :(得分:0)

定义合同

/**
 * Contract that will allow Types with id to have generic implementation.
 */
public interface IdentifierType<T> {
  T getId();
}

申请合同

public enum EntityType implements IdentifierType<Integer> {
  ENTITY1(1, "ONE), ENTITY2(2, "TWO");

  private Integer id;
  private String name;

  private EntityType(int id, String name) {
    this.id = id;
    this.name = name;
  }

  public static EntityType valueOf(Integer id) {
    return EnumHelper.INSTANCE.valueOf(id, EntityType.values());
  }

  @Override
  public Integer getId() {
    return id;
  }
}

<强>辅助/的Util

public enum EnumHelper {
  INSTANCE;

  /**
   * This will return {@link Enum} constant out of provided {@link Enum} values with the specified id.
   * @param id the id of the constant to return.
   * @param values the {@link Enum} constants of specified type.
   * @return the {@link Enum} constant.
   */
  public <T extends IdentifierType<S>, S> T valueOf(S id, T[] values) {
    if (!values[0].getClass().isEnum()) {
        throw new IllegalArgumentException("Values provided to scan is not an Enum");
    }

    T type = null;

    for (int i = 0; i < values.length && type == null; i++) {
        if (values[i].getId().equals(id)) {
            type = values[i];
        }
    }

    return type;
  }
}

答案 8 :(得分:0)

Nihal,您收到了很多答复,回答如何找到正确的枚举元素。 但是我觉得您还希望使用“通过”之类的元素名称,而不是“已通过”

请致电 .name()以获得“通过” 。 扩展Josua的答案:getById(40L).name();

和EnumStatus.PASSED.getName()以获取您的情况“已通过”

答案 9 :(得分:0)

模式可以为您提供帮助:

public interface Identifiable<T extends Number> {

    @Nonnull
    T getId();
}

public final class GettableById<K extends Number, V extends Enum<V> & Identifiable<K>> {

    @Nonnull
    private final Map<K, V> idToValue;


    public GettableById(@Nonnull V[] values) {
        this.idToValue = Arrays.stream(values)
                .collect(Collectors.toUnmodifiableMap(Identifiable::getId, v -> v));
    }

    @Nonnull
    public V getById(@Nonnull K id) {
        var value = idToValue.get(id);
        if (value != null) {
            return value;
        }
        throw new NullPointerException("Cannot get value by id: %s".formatted(id));
    }
}

public enum DataType implements Identifiable<Short> {

    ANNUAL((short) 1), QUARTERLY((short) 2);

    private static final GettableById<Short, DataType> companion = new GettableById<>(values());

    @Nonnull
    private final Short id;


    public static DataType getById(Short id) {
        return companion.getById(id);
    }

    DataType(@Nonnull Short id) {
        this.id = id;
    }

    @Nonnull
    @Override
    public Short getId() {
        return id;
    }
}

答案 10 :(得分:0)

自从Java 8引入Optional以来,您就可以将其用作返回类型。考虑像这样实现:

public static Optional<EnumStatus> fromId(Long id) {
    for (EnumStatus e: values()) {
        if (e.id.equals(id)) {
            return Optional.of(e);
        }
    }
    return Optional.empty();
}

或使用Stream API:

public static Optional<EnumStatus> fromId(Long id) {
    return Stream.of(values())
            .filter(e -> e.id.equals(id))
            .findFirst();
}

有效Java第三版一书中的作者 Joshua Bloch 推荐了一种有效的解决方案,该解决方案也使用Optional作为返回类型:

private static final Map<String, Operation> stringToEnum =
    Stream.of(values()).collect(
        toMap(Object::toString, e -> e));

public static Optional<Operation> fromString(String symbol) {
    return Optional.ofNullable(stringToEnum.get(symbol));
}

Bloch使用Optional的理由:

...请注意,fromString方法返回一个Optional<Operation>。这个 允许方法指示传入的字符串不代表 有效的操作,它迫使客户面对这种可能性