我创建了一个包含 4 种地址格式的枚举。我知道哪个国家/地区使用哪种格式,并且我正在尝试创建一个 HashMap,其中包含国家/地区作为键,格式作为值。我想获得一个时间复杂度为 O(1) 的国家的地址格式。
static final HashMap<String, Format> countries = new HashMap<>();
static {
for (Format format : Format.values()) {
for (String country : format.getCountries()) {
countries.put(country, format);
}
}
}
public static Optional<Format> fromCountry(String country) {
return Optional.ofNullable(countries.get(country));
}
示例格式枚举为:
FORMAT1("[num] [road]", ["AD", "AE", "AG", "......", "ZA", "ZM", "ZW"])
我的应用程序是多线程的,但在初始化后我不会将任何数据放入此地图,并且我只会使用上面的
fromCountry()
方法从该地图中获取值。这种情况下我可以使用HashMap还是需要使用ConcurrentHashMap?还有比使用这些更好的方法吗?
您正在重塑国际化。已经有很多工具了。您是否检查过它们并写了一些客观原因来取消“所有”流行工具的资格,从而证明重新发明特定轮子是合理的?如果没有,针对您的具体情况的最正确答案是“删除所有这些并使用这些库之一”。 简单的网络搜索即可找到您需要的一切。 请注意,语言 i18n 与本地自定义 i18n 有很大不同,而本地自定义 i18n 与货币 i18n 也有些不同。然而,i18n 库可以处理所有这些。
错误使用
Optional
getCountry
编写自定义方法,则返回
Optional
很少合适。如果您的 i18n 组合不知道如何为提供的语言环境完成工作,那么调用者可能不知道该怎么做。方法(以及一般的编程)是关于抽象并解决一次问题,然后在任何地方使用该解决方案,而不是在整个代码库中临时重新实现该解决方案一千次。
考虑以下场景的普遍合适的解决方案:“我想根据区域设置值查找地址格式...(哦,对了,我确实需要考虑如果不知道此信息会发生什么)”并在这个方法中写
一次。 我无法想象
Optional
在这里是一个很好的解决方案。当然,
null
并不比可选好多少 - 但是,除了“空”或“可选”之外,还有更多选项。最有可能的是,您应该定义一个标准后备格式并在“呃我不知道”的情况下返回该格式。可能使用某种日志记录框架来注册请求未知区域设置(该框架可能只想为每个唯一的未知区域设置值记录一次)糟糕的代码风格
Locale
概念(在
java.util
中);该参数大概应该是 Locale
而不是 String
。我这里需要ConcurrentHashMap
HashMap
就可以了。至少,这很可能取决于您的代码的设置方式。关键规则是“发生在之前”。任何时候一行代码写入任何字段(并且
HashMap
,自然地,当您调用 put
时,会写入很多字段),那么任何其他代码行尝试从该字段读取的操作是否实际上最终会看到更新取决于这两行之间是否存在 Happens-Before 关系。如果是的话,阅读代码肯定会看到。如果不是,可能会也可能不会——JVM 每次都可以自由地掷一枚邪恶的硬币来决定。你想避开恶币,所以你想建立HB关系。幸运的是:
thread.start()
然后开始创建线程,那么这些线程中的所有代码都保证可以看到写入。 plain
HashMap
.get()
调用保证不会写入任何字段。因此,get()
本身不能与其他 get
调用发生冲突。
ConcurrentHashMap
- 只有当你首先创建所有线程并启动它们时才会出现这种情况,但它们都会等待某个信号,
然后你填充哈希图, then 线程收到继续执行的信号。即使这样仍然可能有效,if信号的发送发生在接收此信号的线程之前,这很可能,但这取决于信号机制(如果是
synchronized
,则发生发生之前, j.u.c 锁也一样,所以,可能)。