Java之HashMap源码分析(第九篇:总结)

(本文基于JDK1.8)

前言

    HashMap的知识点很多,分析完它的源码,自我感觉成长不少,我知道有部分源码还没有分析,包括JDK1.8新增加的添加元素的方法,判断是否某个Key对象的地方,判断是否包含某个Value对象的方法,还有红黑树结构(这块是软肋)

 

总结

1、HashMap实现了Map接口

2、它是一个非线程安全类,不能在多线程环境下使用

3、添加添加时,允许key对象与value对象为null

4、HashMap中的元素是完全无序的,遍历元素的时候会有影响

5、底层存储使用的是数组,因为HashMap对象持有了一个数组对象

6、每一个元素在数组的位置(下标)在HashMap中也称为桶(tong),比如哈希表的容量是10,那么就说是有10个桶(英文:bucket),这是因为哈希冲突时,可能有多个元素与数组下标相关

7、HashMap在JDK1.7中的存储结构是数组+单链表,在JDK1.8是数组+单链表+红黑树,引入红黑树的目的是为了解决单链表过长时,查找元素的时间复杂度为O(n)

8、单链表和红黑树的存在是为了解决哈希冲突(Key对象不同,但hashCode相同):即 key1 != key2,但key1.hashCode() == key2.hashCode()

9、JDK1.7中数组的每一个桶,指向的一直都是单链表的头结点(第一个结点),新结点都是放在头结点处(在JDK1.7中,新的结点永远做单链表的第一个结点,这是头插法);JDK1.8改了规则,采用尾插法,新结点作为最后一个节点

10、JDK1.8开始,当单链表的长度大于TREEIFY_THRESHOLD时,TREEIFY_THRESHOLD的值是8,但是我发现用的时候都-1了(因为当前插入的结点还没计算到总数中)

11、Entry结点类(Java1.7)在Java1.8中改为Node结点类,JDK1.7中的数组中的每一个元素是一个Entry对象,JDK1.8中则是Node对象

a、Java1.7的时候是Entry类

b、Java1.8的时候改叫为Node,实现了Entry

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash; //经过hash函数计算后hash值,根据数组长度与key的hashCode,进行位与运算,其实就是高效取模
        final K key; //持有的key对象的引用
        V value;    //持有的value对象的引用
        Node<K,V> next;  //指向下一个结点对象的引用

   //省略好多代码

}

 

HashMap类结构

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

}

a、继承AbstractMap(它真正实现了Map接口中的通用方法)

b、实现Map ,HashMap代码阅读性显著提高(AbstractMap也实现Map接口)

c、实现Cloneable,支持clone对象

d、实现Seralizable,支持序列化

 

HashMap添加元素的方法

1、put(K key, V value)  传入key与value,插入一个元素

2、putAll(Map<? extends K, ? extends V> m) 把另外一个哈希表的所有元素合并进来,嘿嘿

3、putIfAbsent(K key, V value) Java1.8新增的哦,只有key不存在的时候,才会添加元素成功哦(就是说如果key已经存在,则不会覆盖掉原来的value)

4、computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

5、computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

6、compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

 

HashMap删除元素的方法

1、remove(Object key) 干掉匹配key的元素,嘿嘿

2、remove(Object key, Object value) 干掉即匹配key、又匹配value的元素

3、clear() 干掉哈希表中的所有元素,欧耶

 

HashMap修改元素的方法

1、replace(K key, V value) 找到匹配的key,替换掉原来的Value,会返回旧的Value

2、replace(K key, V oldValue, V newValue) 找到匹配的key,同时匹配Value,然后替换成新的Value,返回值是boolean类型

3、replaceAll(BiFunction<? super K, ? super V, ? extends V> function) 这个,我懵逼了,注释怎么都么有?大伙儿baidu搜一下?

 

HashMap查找元素的方法

1、get(Object key) 根据key,返回value,欧耶

2、getOrDefault(Object key, V defaultValue) key存在,返回value,不存在,返回defaultValue(Java1.8新增)

 

HashMap 的2种遍历方式

1、Iterator对象……这是entry组成的Set

  Map map = new HashMap();
  Iterator iter = map.entrySet().iterator();
  while (iter.hasNext()) {
  Map.Entry entry = (Map.Entry) iter.next();
  Object key = entry.getKey();
  Object val = entry.getValue();
  }

 

 

2、Key组成的Set

  Map map = new HashMap();
  Iterator iter = map.keySet().iterator();
  while (iter.hasNext()) {
  Object key = iter.next();
  Object val = map.get(key);
  }

 

HashMap的知识点很多,非常适合做面试题

1、数组的默认容量,用的2的幂(默认16,2的4次幂),因为用位运算(位与)替换了取模运算,为了性能,所以必须是2的N次方,数组的容量参与hash()方法的计算

2、加载因子:容量*加载因子 == 扩容阈值

3、扩容知识点,数组变大了,就要重新计算每一个key的hash值(这里注意,HashMap中没有直接使用key的hashCode()),称为resize(rehash)

4、查找速度无冲突O(1),有冲突O(n),大于等于8个结点时,为O(logn)

5、哈希函数设计

 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值