- 学习 HashMap 的构造方法、合适的遍历、复制转換等
- 学习 HashMap 必须要知道的底层原理
- TreeMap、LinkedHashMap 比 HashMap 更好吗?
- 看图说话,对比各 Map 实现类的速度
- HashMap
- HashMap 有几种构造方法?怎么用?
- HashMap 底层原理
- 存取的过程
- 怎样进行初始化
- 扩容
- LinkedHashMap、TreeMap 的用法
- 性能分析
V put(K key, V value);V get(Object key);int size();V remove(Object key);boolean containsKey(Object key);
staticclassEntry<K, V> implementsMap.Entry<K, V> {
finalKkey;
Vvalue;
Entry<K, V> next;
finalinthash;
}实验结果:entrySet() 优于 Iterator 优于 values() 优于 keySet()
for (Stringkey : userMap.keySet()) {
value = userMap.get(key);
}for (Integerv : userMap.values()) {
value = v;
}for (Map.Entry<String, Integer> entry : userMap.entrySet()) {
value = entry.getValue();
}Iterator<Map.Entry<String, Integer>> it = userMap.entrySet().iterator();
while (it.hasNext()) {
Entry<String, Integer> entry = it.next();
value = entry.getValue();
}- 了解 HashMap 底层原理是每个 Java 工程师的必修课
- 可以更好的进行 HashMap 的优化设计
- 与行业内同事沟通交流的话题
Map<Integer, String> intMap = newHashMap<>();
intMap.put(120, "a");
intMap.put(37, "b");
intMap.put(61, "c");
intMap.put(40, "d");
intMap.put(92, "e");
intMap.put(78, "f");{37=b, 120=a, 40=d, 92=e, 61=c, 78=f}Map<String, Integer> strMap = newHashMap<>();
strMap.put("yuwen", 90);
strMap.put("yinyue", 78);
strMap.put("tiyu", 88);
strMap.put("shuxue", 60);
strMap.put("meishu", 98);{yuwen=90, shuxue=60, tiyu=88, yinyue=78, meishu=98}staticfinalinthash(Objectkey);用 hashCode() 方法将 key 转换成 hash 码后并进行优化得到优化后的 hash 码。
例如:将 yuwen 这个字符串优化后的 hash 码是 115347492。
staticfinalintindexFor(inth, intlength);对优化后的 hash 码,进行取址,确定在 HashMap 的位置。
例如:115347492 在长度是 16 的 HashMap 中,取址的坐标是 4。
staticfinalintDEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16staticfinalfloatDEFAULT_LOAD_FACTOR = 0.75f;public HashMap()public HashMap(int initialCapacity)public HashMap(int initialCapacity, float loadFactor)
new HashMap(5),初始化的长度就是$5$ 吗?
初始化长度为传入长度的最小的
new HashMap(10000, 0.75),要录入的数据有$10000$ 条,会产生扩容吗?
初始化长度为
/** * 1、创建 10 个 HashMap,每个 HashMap 含有 10w 条记录 * 2、传递不通的构造方法的参数,比较速度 * 3、实验参数:构造方法传参 (16, 0.75f) 和 (16384, 0.75f) */initialCapacity 的设置要合适,适应业务需求,尽量避免扩容。
- 判断是否为空、删除结点、清空 HashMap 对象
- 判断是否有某个 key、判断是否有某个 value
- HashMap 替换某个 key 的 value
/** * 用到的技术点: * 1、isEmpty * 2、remove, clear * 3、containsKey, containValue * 4、replace * 5、put, putIfAbsent * 6、forEach((key, value) -> System.out.println(key + ": " + value)) * 7、getOrDefault(Object key, V defaultValue) */boolean isEmpty();V remove(Object key);void clear();boolean containsKey(Object key);boolean containsValue(Object value);default V replace(K key, V value)default boolean replace(K key, V oldValue, V newValue)V put(K key, V value);default V putIfAbsent(K key, V value)default void forEach(BiConsumer<? super K, ? super V> action)default V getOrDefault(Object key, V defaultValue)
/** * 1、分别给 HashMap 和 LinkedHashMap 录入 100w 条记录,并循环遍历,观察耗时 * 2、都采用不带参的空构造方法 */put操作:HashMap 优于 LinkedHashMapget操作:LinkedHashMap 优于 HashMap
- 录入顺序
- 使用顺序
publicLinkedHashMap(intinitialCapacity,
floatloadFactor,
booleanaccessOrder)newLinkedHashMap<>(16, 0.75f, true)publicclassLruMap<K, V> extendsLinkedHashMap<K, V> {
privateintmaxSize;
publicLruMap(intmaxSize) {
super(16, 0.75f, true);
this.maxSize = maxSize;
}
@OverrideprotectedbooleanremoveEldestEntry(Map.Entry<K, V> eldest) {
returnsize() > this.maxSize;
}
}- 对 TreeMap 实现增、删、遍历、排序等操作
- 存取耗时对比
put操作:HashMap 优于 LinkedHashMap 优于 TreeMapget操作:LinkedHashMap 优于 TreeMap 优于 HashMap


