【问题标题】:Java: Using an enum as an array referenceJava:使用枚举作为数组引用
【发布时间】:2012-03-13 16:33:48
【问题描述】:

我想引用一个枚举类型的数组。这是 C++(我的起源)中的一个非常标准的东西,但是我不确定这在 Java 中是否可行/可取。

例如,我想要一个枚举,例如:

public enum Resource {
    COAL,
    IRON
}

那以后我想这样引用:

Amount[COAL] // The amount of coal
Price[IRON]  // The price of iron

我不想创建ResourceAmountPrice 字段,因为我想要按资源类型分组的对象列表(资源订单)。手动为Resource的每种类型分配一个int并不比public static int final BLAH好,我觉得没什么收获。

本质上,我正在寻找标记事物的 C++ 枚举。我意识到这可能是用 Java 做事的“错误”方式,所以请随时为我指明正确的 Java 精神方向。

【问题讨论】:

    标签: java arrays enums


    【解决方案1】:

    在 C++ 中,枚举实际上是整数的别名。在 Java 中,它们是“正确的”对象——这就是为什么不能将它们用作数组引用的原因。

    如果您想在数组中查找与特定枚举对象关联的值 - 这对我来说听起来像是一个 Map!用EnumMap<Resource, Double> 替换这些数组怎么样?

    EnumMap 类针对与枚举键一起使用进行了优化,因此它最终会在幕后使用以枚举的序数(整数)值为键的数组。因此,它比通用的 hashmap 快得多,并且您可以获得基于数组的解决方案的速度以及 Map 的语义表达能力 - 这是两全其美的选择。

    【讨论】:

    • 啊!这正是我想要的,非常感谢!
    【解决方案2】:

    你几乎可以做到。与 enum 只是 int 的 C++ 相比,Java 的 enum 是类。所以你不能用它作为数组的索引。但是每个枚举元素都有ordinal() 是int,所以你可以说

    amount[COAL.ordinal()]
    price[IRON.ordinal()]
    

    但你有更好的方法。可以给枚举添加方法,所以它看起来像:

    IRON.price(amounts)
    COAL.amount(prices)
    

    我认为这种方法要好得多。

    【讨论】:

      【解决方案3】:

      每个 Java 枚举元素都有一个与之关联的序数,根据枚举中的定义顺序从零开始索引。只需使用例如

      COAL.ordinal()
      

      但是,在我看来,您最好创建一个类,例如使用金额和价格字段订购,然后保留这些字段的集合,例如在由枚举元素索引的 Map 中。

      例如

      Map<Resource, Order> orders = new HashMap<Resource, Order>();
      orders.put(Resource.COAL, new Order(price, amount));
      

      【讨论】:

        【解决方案4】:

        我想你正在寻找 EnumMap,http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumMap.html

        它不完全是一个数组,但是因为键是一个枚举,所以它仍然是节省空间的。

        结果如下:

        amount.get(Resource.COAL)

        【讨论】:

          【解决方案5】:

          地图非常适合更多动态数据。但是您还必须编写所有检查双重名称、双重值、现有名称/值和所有内容的代码。即使在这种情况下,如果你犯了错误,它也只会在运行时被发现。

          对于更多静态数据,最好不要使用原始枚举,而是使用new type enums from Java 6。他们很棒!编译器会发现错误。

          public enum Resource{
              COAL(0), IRON(1);
              int index;
              private Resource(int index){
                  this.index=index;
              }
          }
          ...
          amount[Resource.COAL.index]=...
          

          但更好的变体是:

          public enum Resource{
              COAL(538,0.5f), IRON(115,1.5f);
              int amount;
              float price;
              private Resource(int amount, float price ){
                  this.amount=amount;
                  this.price=price;
              }
          }
          ...
          Resource.COAL.amount=...
          

          你可以使用他们的名字。

          你可以循环遍历所有枚举:

          for(Resource resourceType: Resource.values()) { 
             String toOutput=resourceType.name()+" amount="+ resourceType.amount;
          }
          

          【讨论】:

            【解决方案6】:

            很遗憾,您需要稍长的语法:

            Amount[COAL.ordinal()] // The amount of coal
            Price[IRON.ordinal()]  // The price of iron
            

            如果这不符合您的喜好,常量可能是您唯一的选择,即

            public class Resource {
                public static final int COAL = 0;
                public static final int IRON = 1;
            
            }
            

            希望对您有所帮助。

            【讨论】:

            • 您真的不应该使用ordinal() - 如果要在enum 中添加另一个字段,或者甚至按字母顺序重新排序,您的代码将会中断并且几乎不可能弄清楚为什么。 Map 是一个更加优雅且类似于 Java 的解决方案。
            • 也许不是……但它回答了 Cramer 的问题。
            • 它(有点)确实,但它也是 “Java 中‘错误’的做事方式”
            猜你喜欢
            • 2010-09-29
            • 1970-01-01
            • 2010-11-02
            • 2016-06-26
            • 2019-11-17
            • 1970-01-01
            • 2022-08-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多