39

我有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) 来获取枚举名称 ( PASSED, AVERAGE, GOOD)。我该怎么做?

4

11 回答 11

68

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

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

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

于 2013-03-13T08:35:02.940 回答
15

这可以使用静态映射和静态初始化器来完成:

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。

于 2013-03-13T08:35:00.800 回答
3

您可以按如下方式进行这项工作:

public static String fromId(long id) {
        for (EnumStatus es : EnumStatus.values()) {
            if (es.id.equals(id)) {
                return es.getName();
            }
        }
        throw new IllegalArgumentException();
}
于 2013-03-13T08:39:22.407 回答
2
public static EnumStatus getById(long id)
{
  for (EnumStatus e : EnumStatus.values())
  {
    if (id == e.getId()) return e;
  } 
  throw new IllegalArgumentException("oh no");
}
于 2013-03-13T08:41:36.787 回答
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;
}
于 2013-03-13T08:38:30.913 回答
1

Nihal,你有很多回答如何找到正确的枚举元素。但我有一种感觉,你也希望元素的名称像"PASSED" 而不是 "Has Passed"

请调用 .name()以获取"PASSED"。扩展约书亚的答案:getById(40L).name();

和 EnumStatus.PASSED.getName() 在你的情况下得到"已通过"

于 2019-12-16T09:12:42.060 回答
0

遍历所有值并比较 Id

for (EnumStatus  enumStatus : EnumStatus.values()) {
   if (..) {..}
}
于 2013-03-13T08:35:10.057 回答
0

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

EnumStatus.X = 40 + 20 * ordinal,

因此您可以利用在幕后生成的静态数组

public static EnumStatus fromId(Long id) {
    int index = (id - 40L) / 20L;
    return values()[index];
}
于 2013-03-13T09:02:05.887 回答
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;
  }
}

助手/实用程序

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;
  }
}
于 2016-08-10T10:33:43.910 回答
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;
    }
}
于 2020-10-06T22:19:58.797 回答
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();
}

或使用流 API:

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

Effective Java 3rd Edition一书中,作者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>. 这允许该方法指示传入的字符串不代表有效的操作,并迫使客户端面对这种可能性

于 2020-11-16T13:46:00.010 回答