在枚举类型上实现“下一个”和“上一个”的最佳方法是什么?

2022-08-31 14:58:44

假设我有一个枚举:

enum E {
    A, B, C;
}

lucasmo 的这个答案所示,枚举值按照初始化的顺序存储在静态数组中,稍后可以使用 检索(克隆)此数组。E.values()

现在假设我想实现,并且使得以下所有表达式的计算结果为:E#getNextE#getPrevioustrue

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

然而,这段代码充其量似乎很麻烦(例如,“空”循环,对计数器变量的可争论滥用,以及最坏情况下可能错误(可能进行思考反射)。for

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


注意:不打算让这个问题是主观的。我对“最佳”实现的要求是要求实现最快,最干净,最易于维护的实现的简写。


答案 1

试试这个:

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

的实现是一个练习,但回想一下,在Java中,模a % b可以返回一个负数previous()

编辑:如建议的那样,创建数组的私有静态副本,以避免每次或被调用数组复制。values()next()previous()


答案 2

或者,人们可以以某种方式沿着以下想法的路线前进:

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. 与另一个答案相反,这种方式做了一些隐式映射;而不是依赖 .当然,这意味着更多的代码;但它也迫使作者考虑添加新常量或删除现有常量意味着什么。当依赖于序数时,您的隐式假设是顺序基于用于枚举常量声明的顺序。因此,当有人在6个月后回来并且必须添加一个新的常量时,他必须明白新的常数Y需要......而不是仅仅附加!ordinal()X, Y, ZX, Z, Y
  2. 在某些情况下,“最后一个”枚举常量将“第一个”作为后继者没有任何意义。想想T恤尺寸的例子。XXL.next() 肯定不是 XS。对于这种情况,使用“可选”是更合适的答案。

推荐