例如,我想制作一个收银机程序。为了紧凑起见,忽略了人们不会使用浮点数作为货币,我的第一直觉是使用面额的枚举,大致如下:
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);
它会因为任何原因而优越吗?
在这样的情况下,两者都可以利用,使用其中一种是否有任何性能优势?一个更可取/更传统吗?更易于维护/适应性更强?
当我应该使用一个而不是另一个时,我可以使用任何经验法则吗?
我想记住的事情:
枚举最好使用(在我所知道的语言中,可能只使用)来提前定义一组已知的项目。这有一个很好的好处,即以非常可读的方式将真正归结为常用"数据"的内容视为代码。
在我看来,任何依赖于频繁硬编码字符串的代码,就像在映射中实现此类数据更难以阅读和维护时需要使用的那样。这导致了"魔弦",这是可以避免的禁忌。
在你去检查之前,它不会立即清楚地图中应该存在什么,也不清楚它是否可能在其他地方被修改。考虑一下,如果你得到了一个错误的枚举值,代码甚至不会编译。弄错了字符串键,你可能要等到很久以后才会注意到。
关于性能,我怀疑两者之间有很大的区别。枚举与对象的处理方式大致相同,我想好处来自于将数据作为对象上的字段而不是哈希查找来访问。
本文没有像我想的那样深入,但可能是一个很好的起点: Java 数据类型的内存消耗
使用枚举作为已知映射的键是很常见的做法,这提供了另一种将数据与一组特定项目相关联的方法(而不是将它们设置为枚举上的字段)。我相信这种方法是我的首选方法,因为在枚举上设置大量字段会使它们感觉太像一个类而不是引用方法。这没有与普通贴图相同的问题,因为由于键必须是枚举,因此您无需担心任何其他键"意外"添加到地图中。似乎Java作为一个整体支持这种方法,因为它们提供了EnumMap
类。
我想说的是,您的两段代码之间的主要区别在于,在枚举的情况下,您有固定的"类型安全"面额列表。在使用字符串和映射时,很容易拼错一些字符串,从而引入难以发现的错误。
,我会使用枚举,它更明智,如果这是其他人使用的东西,那么如果您使用几乎任何 IDE,enum 都会为您显示关联的值,就像您在使用地图一样,键或值都不容易获得。还有其他原因,但这是我想到的原因。
映射设计适用于它会因为任何原因而优越吗?
动态数据,而枚举设计适用于固定数据。
在这种情况下,可以使用,是否有任何 使用一个优于另一个的性能优势?
微不足道。
一个更可取/更传统吗?
只有在考虑要解决的具体问题时。
更易于维护/适应性更强?
同样,这取决于您要解决的问题。
当我应该使用一个时,是否有任何经验法则可以使用 另一个?
是否使用编译时已知的有限、不变的数据集。