一、概述
二、HashMap
1、数据结构
2、应用
3、不要用 HashMap 做本地缓存
一般我们声明 HashMap 时,使用的都是默认的构造方法:HashMap<K, V>,但是它还有另外一个构造方法:HashMap(int initialCapacity, float loadFactor),其中参数 initialCapaticy 为初始容量,loadFactor 为加载因子;如果在默认情况下,一个 HashMap 的容量为 16,加载因子为 0.75,那么阈值就是 12,所以在往 HashMap 中 put 的值到达 12 时,它将自动扩容两倍,如果两个线程同时遇到 HashMap 的大小达到 12 的倍数时,就很可能会出现在将旧的 Entry[] 转移到一个新的 Entry[] 的过程中出现问题,从而导致最终的 HashMap 的值存储异常。
再分析一下空间效率,拿 HashMap<Long, Long> 举例。在 HashMap<Long, Long> 结构中,只有 Key 和 Value 所存放的两个长整型数据是有效数据,共 16B (2 X 8B)。这两个长整型数据包装成 java.lang.Long 对象之后,就分别具有 8B 的 MarkWord、8B 的 Klass 指针,在加 8B 存储数据的 long 值。在这两个 Long 对象组成 Map.Entry 之后,又多了 16B 的对象头,然后一个 8B 的 next 字段和 4B 的 int 型的 hash 字段,为了对齐,还必须添加 4B 的空白填充,最后还有 HashMap 中对这个 Entry 的 8B 的引用,这样增加两个长整型数字,实际耗费的内存为 (Long(24B)X2) + Entry(32B) + HashMap Ref(8B) = 88B,空间效率为 16B/88B = 18%,实在太低了。
三、ConcurrentHashMap
1、数据结构
2、应用