使用Map时,需要考虑什么

 

关于Java中的Map,已有很多文章讲述其较为完整的知识点了,本文不会再谈论这些知识点,而是从实际使用的角度,讲述笔者会考虑什么问题,算是对知识的一个应用,毕竟学了,最后还是要落地到使用中。

首先,在使用Map前,我们先考虑第一个问题,为什么要使用Map这种数据结构。在工作中,笔者会想到使用到Map的场景通常有:

  1. 对数据按某种规则分组,用Key做分组的标识;
  2. 缓存,用Key做索引查找数据。

在确认要使用Map后,便需要考虑使用哪种Map。通常最先想到,也最常用的是HashMap。但需要注意两个地方,是否对线程安全有序性有要求。

线程安全

  1. 如果是不存在并发写入,则可以直接使用HashMap
  2. 如果存在并发写入的情况,就需要使用线程安全的ConcurrentHashMap

有序性

  1. 如果是想按Key进行排序,就应该使用TreeMap
  2. 如果是想按写入的顺序排序,则可以使用LinkedHashMap。如果要实现LRU,LinkedHashMap则是不二之选。

如果对有序性和线程安全同时有要求,那么需注意TreeMapLinkedHashMap都不是线程安全的。对于TreeMap,可以使用Collections.synchronizedSortedMapsynchronized和锁等方法来同步。同样LinkedHashMap,也可以使用Collections.synchronizedMapsynchronized和锁来保证线程安全。

下面再进一步讨论对于使用HashMap的情况,如果是准备作为缓存来使用,且希望缓存可以自动清理,则可以使用WeakHashMap

确定了Map的类型,最后会考虑的是,是否需要指定初始化大小

在使用HashMapConcurrentHashMapLinkedHashMap时,如果我们能预先知道存放元素的数量,则可以根据下面的公式计算出初始化大小并传入构造函数中,从而避免不必要的扩容。

\[initialCapacity = (元素个数 / 负载因子) + 1\]

总结:

  1. 是否要使用Map;
  2. 使用什么类型的Map合适;
  3. 是否可以指定初始化大小。

以上就是笔者目前在使用Map时,会去考虑的一些事项,还有什么需要考虑的,欢迎留言讨论。