在可以使用地图的地方使用枚举是否有优势,反之亦然?

Are there advantages to using an enum where you could use a map and vice versa?

比如说我要做一个收银程序。为了简洁起见,忽略不会 use floats for currency 我的第一直觉是使用枚举作为面额,类似于 :

private enum Currency {
        ONE_HUNDRED(100.00f),
              FIFTY( 50.00f),
             TWENTY( 20.00f),
                TEN( 10.00f),
               FIVE(  5.00f),
                TWO(  2.00f),
                ONE(  1.00f),
        HALF_DOLLAR(  0.50f),
            QUARTER(  0.25f),
               DIME(  0.10f),
             NICKEL(  0.05f),
              PENNY(  0.01f);

        private final float value;

        Currency(float value) {
            this.value = value;
        }

        public float getValue() {
            return this.value;
        }

        @Override
        public String toString() {
            return this.name().replace("_", " ");
        }
    }

但最后我凭直觉,没有深谋远虑,为摩尔斯电码转换器做了类似的事情,有人建议我改用地图,明确地 Bimap。我看到了那个系列在那种特定情况下的吸引力,但总的来说,我想问的是,当另一个可以使用时,是否有任何理由更喜欢一个?如果我这样做而不是上面的代码:

Map<String, Float> currency = new LinkedHashMap<>();

    currency.put("One Hundred", 100.00f);
    currency.put("Fifty", 50.00f);
    currency.put("Twenty", 20.00f);
    currency.put("Ten", 10.00f);
    currency.put("Five", 5.00f);
    currency.put("Two", 2.00f);
    currency.put("One", 1.00f);
    currency.put("Half Dollar", 0.50f);
    currency.put("Quarter", 0.25f);
    currency.put("Dime", 0.10f);
    currency.put("Nickel", 0.05f);
    currency.put("Penny", 0.01f);

它会因为任何原因而更优越吗?

在这些情况下都可以使用,使用一个比另一个有什么性能优势吗?还有一个preferable/conventional?更多 maintainable/adaptable?

当我应该使用一个而不是另一个时,是否有我可以使用的经验法则?

我想说的是,您的两段代码之间的主要区别在于,在枚举的情况下,您有固定的面额列表 "type-safe"。在使用字符串和映射操作时,很容易拼错某些字符串,从而引入难以发现的错误。

在这种情况下我会使用枚举,它更明智,如果这是其他人使用的东西,枚举会为您显示相关值,如果您几乎使用任何 ide,就好像您正在使用地图一样,键或值都不容易提供给您。还有其他原因,但这是我想到的。

以下是我要记住的事项:

最好使用枚举(并且在我所知道的语言中,可能只使用)提前定义一组已知的项目。这有一个很好的好处,就是以一种非常可读的方式将真正归结为经常使用的 "data" 作为代码处理。

在我看来,任何依赖频繁硬编码字符串的代码(如果在地图中实现类似数据时需要使用)都更难阅读和维护。这导致 "magic strings",这是可以避免的禁忌。

在您去检查之前,目前还不清楚地图中应该存在什么,也不清楚它是否可能在其他地方被修改。考虑一下,如果你得到一个错误的枚举值,代码甚至不会编译。弄错字符串键,您可能要等到很久以后才会注意到。

关于性能,我怀疑两者之间存在很大差异。枚举在很大程度上被视为与对象相同,我认为好处来自于将数据作为对象上的字段而不是散列查找来访问。

本文没有像我希望的那样深入,但可能是一个很好的起点:Memory Consumption of Java Data Types

使用枚举作为已知地图的键是很常见的做法,这提供了另一种将数据与一组特定项目相关联的方法(而不是将它们设置为枚举中的字段)。我相信这种方法将是我的首选方法,因为在枚举上设置大量字段会使它们感觉太像 class 而不是引用方法。这不存在与法线贴图相同的问题,因为键必须是枚举,因此您无需担心任何其他键 "accidentally" 被添加到贴图。似乎 Java 作为一个整体支持这种方法,因为它们提供了 EnumMap class.

Would it be superior for any reason?

Map 设计适用于动态数据,而枚举设计适用于固定数据。

In cases like these were either could be utilized, are there any performance advantages to using one over another?

微不足道。

Is one more preferable/conventional?

仅在考虑要解决的具体问题时。

More maintainable/adaptable?

同样,这取决于您要解决的问题。

Is there any rule of thumb I could use for when I should use one over the other?

您是否正在使用编译时已知的有限、不变的数据集。