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

新手上路,请多包涵

假设我有一个枚举:

 enum E {
    A, B, C;
}

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

现在假设我要实现 E#getNextE#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 的类似方法。

然而,这段代码充其量看起来很麻烦(例如,“空” for 循环,计数器变量的可争论的滥用,并且在最坏的情况下可能是错误的(思考反射,可能)。

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


注意:不希望 这个问题是主观的。我对“最佳”实现的要求是要求实现速度最快、最干净且最易于维护的简写。

原文由 wchargin 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 569
2 个回答

尝试这个:

 public enum A {
    X, Y, Z;

    private static final A[] vals = values();

    public A next() {
        return vals[(this.ordinal() + 1) % vals.length];
    }
}

previous() 的实现留作练习,但请记住, 在 Java 中,取模 a % b 可以返回负数

编辑:按照建议,制作 values() 数组的私有静态副本,以避免每次调用 next()previous() 数组复制

原文由 Jim Garrison 发布,翻译遵循 CC BY-SA 4.0 许可协议

或者,可以按照以下想法以某种方式进行:

 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. 在某些情况下,“最后”枚举常量将“第一个”作为后继者没有任何意义。以 T 恤尺码为例。 XXL.next() 肯定不是 XS。对于这种情况,使用 Optional 是更合适的答案。

原文由 GhostCat 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题