在枚举types上实现`next`和`previous`的最好方法是什么?

假设我有一个枚举:

enum E { A, B, C; } 

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

现在假设我想要实现E#getNextE#getPrevious ,使得以下所有expression式都计算为true

 EAgetNext() == EB EBgetNext() == EC ECgetNext() == EA EAgetPrevious() == EC EBgetPrevious() == EA ECgetPrevious() == EB 

我目前的getNext实现如下:

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

和一个类似的方法getPrevious

但是,这个代码看起来很麻烦(例如,“空”循环,有争议的滥用反variables,并且可能在最坏情况下是错误的(可能会思考)。

在Java 7中为枚举types实现getNextgetPrevious方法的最佳方式是什么?


注:打算这个问题是主观的。 我对“最佳”实施的要求是要求最快,最干净,最可维护的实施的速记。

尝试这个:

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

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

编辑:build议,使values()数组的私有静态副本,以避免数组复制每次next()previous()被调用。

或者,我们可以按照下面的想法去做:

 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. 可能会出现这样的情况:对于“last”枚举来说,“first”作为后继是不变的。 以T恤大小为例。 XXL.next()肯定不是XS。 对于这种情况,使用可选是更合适的答案。