在枚举types上实现`next`和`previous`的最好方法是什么?
假设我有一个枚举:
enum E { A, B, C; }
如Lucasmo的 答案所示,枚举值按照它们初始化的顺序存储在一个静态数组中,稍后可以使用E.values()
检索(克隆)该数组。
现在假设我想要实现E#getNext
和E#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实现getNext
和getPrevious
方法的最佳方式是什么?
注:我不打算这个问题是主观的。 我对“最佳”实施的要求是要求最快,最干净,最可维护的实施的速记。
尝试这个:
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(); } }
笔记:
- 与其他答案相反,这种方式做了一些隐式映射; 而不是依靠
ordinal()
。 当然,这意味着更多的代码; 但它也迫使作者考虑添加新的常量或删除现有的常量意味着什么。 在依赖序数的时候,你的隐含的假设是,这个命令是以用于枚举常量声明的顺序为基础的。 所以当6个月后有人回来,并且必须增加一个新的常量时,他必须明白新的常量Y需要X, Y, Z
…而不是仅仅追加X, Z, Y
! - 可能会出现这样的情况:对于“last”枚举来说,“first”作为后继是不变的。 以T恤大小为例。 XXL.next()肯定不是XS。 对于这种情况,使用可选是更合适的答案。