首先hashmap的话是一个常用的集合类框架,也是一个典型的数据结构,也是Java程序员最常用的,用于映射处理的数据。我们从整体上来看的话hashmap是由数组+链表+红黑树实现的。所以它具有了数组的查询效率和链表的添加、删除效率。而且数组也是hashmap的主体,存储数据的方式是使用的hashcode进行计算得到hash值,然后进行存储的。但是这样的话可能就会出现hash冲突的问题了,所以我们使用了链表的方式来解决这个hash冲突的问题,数组中的元素不单单只是一个元素,它还是一个链表的头结点。当我们遇到hash冲突的时候,我们只需要直接把元素插入当前节点的头结点位置就可以了,这样插入的方式是头插法,头插法在jdk1.8之后就改为了尾插法,这样的话是为了避免链表死循环。
红黑树的话就是当链表中的阈值大于8的时候,数组的长度大于64的时候,就会转换成红黑树了,但是当红黑树内的节点少于6个的时候就会转换成链表了。
hash冲突:就是说当我们使用hashcode进行计算时,得到的hash值在插入的时候,要插入的位置已经有了元素,这就是hash冲突,也是hash碰撞中的一点。
hashmap的初始长度是16,加载因子是0.75,当hashmap中的元素超过16*0.75=12个的时候,那么我们就需要进行扩容了,扩容的话是以2倍的形式进行扩容的,如果说之前的容量是16那么扩容后的容量就是32了。另外hashmap的线程是不安全的,因为它可以在任一时刻让多个线程同时写一个hashmap,这样的话会导致数据的不一致。
为什么不使用二叉树呢?主要是因为二叉树的趋势是递增或者递减,这样的话二叉树就会变成链表,就失去了二叉树的意义。
另外hashmap在遍历的时候是顺序是不确定的,因为是无序的。另外hashmap的主键key是可以有一个null值的,但是它的value值是可以有多个null值的。
另外hashmap中的键值对在jdk.8之前被称为entry,但是在jdk1.8之后就被称为node,node不仅包含了键值对key-value,还包含了计算出来的hash值,另外还包含了下一个节点的引用,如果下一个节点没有元素的话,那么node=null。
Hashmap
- 根据键的hashcode值来存数据
- 只允许一条记录的键为null,可以允许多条记录的值为null;(也就是说,每一个键只有唯一的,但是值可以有相同的)。
- 线程不安全
- 无序的
- 初始长度为16
- 加载因子为0.75
Hashmap的底层原理实际上是数组+链表的结合
数组的优缺点:
- 连续存储
- 查找效率高
- 添加、删除操作效率低
链表的优缺点:
- 离散存储
- 添加、删除效率高,扩展灵活
- 不能随机查询