我尝试检查用户帐户类型是否与多个Strings
中的一个匹配。
在办公室里有争论是否应将其表示为enum
,每个条目包含不同的字符串,或Set
Strings
。虽然Set
可能更有效,但枚举可能在风格上更优越,因为它更清楚地用于逻辑流程。
这两种方法有哪些优点?
答案 0 :(得分:22)
实际上,Set<String>
在搜索时的性能方面更有效。但是,我不希望你有几千个帐户类型,但有几个,所以你在搜索时实际上并没有感觉到差异。但是,这种方法存在一个问题 - 您可以将String
添加到Set
,这很脆弱。
我个人更喜欢使用enum
,特别是如果您不希望会引入更多帐户类型。如果你有一个Set<AccountType>
,你可以使用你可以添加的值进行限制(即你可以添加仅帐户类型,但不能添加任何内容,例如使用{的方法{1}})。这种方法的问题是Open/Closed Principle - 考虑您对Set<String>
变量的switch
语句以及所有相应的AccountType
s。然后,如果您引入新 case
常量,则必须更改AccountType
语句(添加新的switch
),这会打破“打开/关闭”原理”。在这种情况下,最新的设计是case
/ abstract class
,称为interface
,其中包含所有特定帐户类型作为子类。
所以,您可以遵循几种方法,但在选择之前,您应该尝试回答“我们将如何使用它?”的问题。
答案 1 :(得分:13)
由于帐户类型(通常)不会动态更改,因此枚举会更好。此外,使用枚举使类型更精确 - 例如没有办法将"Hello, World!"
与帐户类型混淆。
答案 2 :(得分:6)
枚举很棒,因为你得到了编译时检查。无效的值只是简单地无法编译,因此它很快就会失败。
当您想要添加其他选项而不编译/发布应用程序的新版本时,字符串集合非常棒。例如,如果在数据库表中配置了有效选项。
答案 3 :(得分:3)
值得注意的是,枚举的valueOf(String)
方法是使用Enum.valueOf(Class,String)
方法实现的,后者又使用HashMap
实现。
这基本上意味着使用AccountTypes.valueOf()
从字符串中查找帐户类型是一种O(1)操作,并且与设置操作一样高效。然后,您可以在程序中使用返回的值(实际的枚举对象),具有完整的类型安全性,更快的比较以及枚举的所有其他好处。
答案 4 :(得分:3)
在我看来,问题在于您使用字符串来表示只能包含一些有效的已知值的数据。 Set可能有助于验证字符串值是否有效,但它不会阻止它变为无效。
我的建议是使用有效的帐户类型定义枚举,并使用到位字符串。如果您有来自外部的输入代表一个帐户类型,那么在enum上添加一个静态方法,如&#34; fromString&#34;它返回一个合适的枚举实例,从而缩短了无效数据被考虑的窗口。
如果您实施了相应的Set
,AccountType
或Comparator
方法,则可以创建compareTo
个hashCode
枚举实例(具体取决于您是否使用TreeSet
或HashSet
等)。如果您需要检查帐户类型的分类,这可能很有用。例如,如果有&#34;本地管理员&#34;,&#34;全局管理员&#34;以及&#34;安全管理员&#34;,您可以定义一个方法isAdmin(AccountType t)
来搜索Set
的{{1}}。例如:
AccountTypes
现在,如果您的案例中有许多不同的帐户类型,包含许多分组,并且查询的性能是一个问题,那么您就可以解决这个问题。
虽然说实话,如果你只有几种帐户类型并且它们很少改变,这可能会过度设计它。如果只有两种帐户类型,则使用相等性检查的简单if语句将比哈希表查找更有效。
同样,性能在这里可能不是真正的问题。不要过早地过度优化或优化。
答案 5 :(得分:1)
根据我的经验,我建议在这种情况下使用枚举。甚至mysql也支持枚举用于需要列接受来自显式声明列表的值的用例。
答案 6 :(得分:0)
我最有效地使用Map<String,Enum> = new HashMap<>();
。