关于Java中的Map,已有很多文章讲述其较为完整的知识点了,本文不会再谈论这些知识点,而是从实际使用的角度,讲述笔者会考虑什么问题,算是对知识的一个应用,毕竟学了,最后还是要落地到使用中。
首先,在使用Map前,我们先考虑第一个问题,为什么要使用Map这种数据结构。在工作中,笔者会想到使用到Map的场景通常有:
- 对数据按某种规则分组,用Key做分组的标识;
- 缓存,用Key做索引查找数据。
在确认要使用Map后,便需要考虑使用哪种Map。通常最先想到,也最常用的是HashMap
。但需要注意两个地方,是否对线程安全、有序性有要求。
线程安全:
- 如果是不存在并发写入,则可以直接使用
HashMap
。 - 如果存在并发写入的情况,就需要使用线程安全的
ConcurrentHashMap
。
有序性:
- 如果是想按Key进行排序,就应该使用
TreeMap
。 - 如果是想按写入的顺序排序,则可以使用
LinkedHashMap
。如果要实现LRU,LinkedHashMap
则是不二之选。
如果对有序性和线程安全同时有要求,那么需注意TreeMap
和LinkedHashMap
都不是线程安全的。对于TreeMap
,可以使用Collections.synchronizedSortedMap
、synchronized
和锁等方法来同步。同样LinkedHashMap
,也可以使用Collections.synchronizedMap
、synchronized
和锁来保证线程安全。
下面再进一步讨论对于使用HashMap
的情况,如果是准备作为缓存来使用,且希望缓存可以自动清理,则可以使用WeakHashMap
。
确定了Map的类型,最后会考虑的是,是否需要指定初始化大小。
在使用HashMap
、ConcurrentHashMap
和LinkedHashMap
时,如果我们能预先知道存放元素的数量,则可以根据下面的公式计算出初始化大小并传入构造函数中,从而避免不必要的扩容。
总结:
- 是否要使用Map;
- 使用什么类型的Map合适;
- 是否可以指定初始化大小。
以上就是笔者目前在使用Map时,会去考虑的一些事项,还有什么需要考虑的,欢迎留言讨论。