在枚举类型上实现`next`和`previous`的最佳方法是什么?

时间:2013-06-09 03:51:42

标签: java optimization enums

假设我有一个枚举:

enum E {
    A, B, C;
}

this answer lucasmo所示,枚举值按照初始化的顺序存储在静态数组中,稍后您可以使用{{1}检索(克隆)此数组}}

现在假设我要实现E.values()E#getNext,以便所有以下表达式都评估为E#getPrevious

true

E.A.getNext() == E.B E.B.getNext() == E.C E.C.getNext() == E.A E.A.getPrevious() == E.C E.B.getPrevious() == E.A E.C.getPrevious() == E.B 的当前实现如下:

getNext

public E getNext() { E[] e = E.values(); int i = 0; for (; e[i] != this; i++) ; i++; i %= e.length; return e[i]; } 的类似方法。

然而,这段代码充其量似乎很麻烦(例如,“空”getPrevious循环,可论证滥用计数器变量,最坏情况下可能是错误的(可能反思)。

在Java 7中为枚举类型实现forgetNext方法的最佳方法是什么?


注意:打算将此问题视为主观。我对“最佳”实现的请求是要求实施最快,最干净,最易维护的简写。

3 个答案:

答案 0 :(得分:74)

试试这个:

public static enum A { 
    X, Y, Z;
    private static A[] vals = values();
    public A next()
    {
        return vals[(this.ordinal()+1) % vals.length];
    }

previous()的实施仅作为练习,但请记住in Java, the modulo a % b can return a negative number

编辑:根据建议,制作values()数组的私有静态副本,以避免每次调用next()previous()时进行数组复制。

答案 1 :(得分:7)

或者,人们可以按照以下想法行事:

public enum SomeEnum {
  A, B, C;

  public Optional<SomeEnum> next() {
    switch (this) {
      case A: return Optional.of(B);
      case B: return Optional.of(C);
      // any other case can NOT be mapped!
      default: return Optional.empty();
  }
}

注意:

  1. 与其他答案相反,这种方式可以进行一些隐式映射;而不是依赖ordinal()。当然这意味着更多的代码;但它也迫使作者考虑添加新常量或删除现有常量意味着什么。当依赖序数时,隐式假设是顺序基于用于枚举常量声明的顺序。因此,当有人在6个月后回来并且必须添加新的常量时,他必须明白新的常量Y需要X, Y, Z ...而不是仅仅追加X, Z, Y
  2. 在某些情况下,对于&#34; last&#34;它可能没有任何意义。枚举常数有&#34;第一&#34;作为继任者。以T恤尺码为例。 XXL.next()肯定不是XS。对于这种情况,使用Optional是更合适的答案。

答案 2 :(得分:-1)

public enum Three
{
    One, Two, Three;

    static 
    public final Three[] values = values();

    public Three prev() {
        return values[(ordinal() - 1  + values.length) % values.length];
    }

    public Three next() {
        return values[(ordinal() + 1) % values.length];
    }
}