1. HashMap简介

  • HashMap是在JDK1.2中引入的Map的实现类。
  • HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。
  • HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。
  • HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。
  • HashMap中key和value都允许为null。但只能有一条记录可以是一个空的key;任意数量的条目可以是空的value

2. 技术本质

2.1 数据结构

jdk 1.7:数组+链表

  • 数组(ArrayList):采用一段连续的存储单元来存储数据。
    • 特点:查询速度快,插入删除速度慢
    • 查询时间复杂度O(1) ;删除插入时间复杂度O(N)
  • 链表(LinkedList):是一种物理存储单元上非连续、非顺序的存储结构
    • 特点: 插入删除速度快,查询速度慢
      • 删除插入时间复杂度O(1);查询时间复杂度O(N)

jdk 1.8:数组+链表+红黑树

链表长度>=8时,链表转变为红黑树

红黑树简介:

自平衡的二叉树

  • 特点
    1,所有的节点非黑即红
    2,根节点一定是黑的
    3,红色节点的子节点一定黑节点,黑节点的子节点可以是红节点, 也可以是黑节点
    4,最底层的叶子节点一定是黑色的空节点
    5,从根节点到任意一个叶子节点所经过的黑色节点的个数一定相同,黑色的节点的高度一致。、
    6,新添加的元素一定是红色的。
  • 修正
    • 涂色:当前节点为红色,父节点也为红色,并且叔父节点也为红色,那么需要将父节点以及叔父节点涂黑,并且将祖父节点涂红
    • 左旋:当前节点为红,父节点为红,叔父节点为黑,并且当前节点为右子叶,那么需要以当前节点为轴进行左旋
    • 右旋,当前节点为红,父节点为红,叔父节点为黑,并且当前节点在左子页,那么需要以父节点为轴进行右旋

2.2 算法

  • 哈希算法(散列)
    • 把任意长度值(key)通过散列算法变换成固定长度的key(地址),通过这个地址进行访问的数据结构。
    • 把关键码值映射到哈希表中,通过哈希表中的位置来访问记录,加快了查找的速度。
      HashMap相关内容
    • 哈希算法底层原理
      (1) Hashcode:通过字符串算出它的ASCII码,进行mod(取模),算出哈希表中的下标。
      取模是为了节省空间
      HashMap相关内容
      (2) 哈希冲突时,要用链表 。
      当两个字符串的ASCII码值相同时,往数组中存放时,就会发生哈希冲突。使用链表来解决此问题。
      HashMap相关内容
      (3) 链表长度>=8时,链表转变为红黑树

3. HashMap和HashTable的区别

HashMap HashTable
JDK版本 JDK1.2版本 JDK1.0版本
父类 AbstractMap Dictionary
线程是否安全 线程不安全 线程安全
效率
是否允许为null值 允许key和value为null值。可以用containsKey()方法来判断。 键值对都不能为空,否则包空指针异常
是否提供contains方法 修改为containsValue和containsKey方法 保留了contains方法
计算hash值方式 首先需要根据元素的 KEY计算出一个hash值,然后再用这个hash值来计算得到最终的位置 直接使用对象的hashCode
遍历方式 Iterator Iterator、Enumeration
数组默认大小 16 11
扩容方式 要求一定为2的整数次幂,容量变为原来的2倍 容量变为原来的2倍加1

相同点:

  • 都是基于哈希表实现的
  • 每个元素是一个key-value对
  • 内部都是通过单链表解决哈希冲突问题
  • 二者都实现了Map接口。
  • 都实现了Serializable接口,支持序列化
  • 都实现了Cloneable接口,能被克隆。

相关文章: