1.HashMap:根据键值hashCode值存储数据,大多数情况下可以直接定位到它的值,但是遍历顺序不确定。所有哈希值相同的值存储到同一个链表中
HashMap只允许一条记录的值为null,允许多条记录的值为null。
HashMap非线程安全,任意时刻可以有多个线程同时写HashMap
为什么HashMap不是线程安全的?
1.比如两个线程同时使用put方法,刚好两个put方法的hashcode值一样,发生了碰撞,那么会发生值的覆盖。
2.当超过限定的threshold后,会进行rehash,所有的元素都要背重新计算一遍,这里会产生死循环,具体参考https://coolshell.cn/articles/9606.html
如何线程安全的使用HashMap?
1.Hashtable
2.ConcurrentHashMap
3.Synchronized Map
2.Hashtable:继承自Dictionary类,并且是线程安全的,任一时间只能有一个线程写HashTable,并发性不如ConcurrentHashMap,ConcurrentHashMap引入了分段锁
HashTable是线程安全的,但是效率低,HashTable使用synchronized,所以所有的线程竞争一把锁。
ConcurrentHashMap不仅线程安全而且效率高,因为它包含了一个Segment数组,将数据分段存储,给每一段数据配一把锁,也就是分段锁技术。
3.LinkedHashMap:保存了记录的插入顺序
4.TreeMap:实现了SortedMap接口,能够把它保存的记录根据键排序,默认是按键值升序排序。
HashMap的内部实现:
1.存储结构:数组+链表+红黑树(JDK1.8之后引入的)
2.HashMap使用哈希表存储,哈希表为了解决冲突,采用开放地址发和链地址法,Java中使用链地址法
3.HashMap的默认构造字段
threshold //所能容纳的key-value对极限
loadFactor //负载因子(默认值0.75)
modCount //记录HashMap内部结构发生变化的次数
size //实际存在的键值对数量
threshold=length*loadFactor-----数组定义好长度后,负载因子越大,所能容纳的键值对个数越多
是一种二叉查找树,每个节点增加一个存储为表示节点颜色(红色或黑色)
对于二叉查找树,由n个节点随机构造的二叉查找树的高度为lgn,则二叉查找树的一般操作的执行时间为O(lgn)
红黑树本质上是二叉查找树,又在二叉查找树的基础上增加了着色和相关的性质是的红黑树相对平衡,从而保证了红黑树查找、插入和删除的时间复杂度最坏为O(log n)
红黑树的5个性质:
1.每个节点或红或黑
2.根节点是黑的
3.每个叶节点是黑的
4.如果一个节点是红的,那么它的两个子节点都是黑的
5.对于任意结点,其到叶节点树微端NIL指针的每条路径都包含相同数目的黑节点