Java面试题 第四部分 数据结构
Collection集合类
HashMap
hashmap的底层结构
数组+List(JDK1.7以及之前)
数组+List(或者红黑树JDK1.8)
hashmap的put和get操作 (Array then List)
- hash到Array的某个节点上;
- 遍历节点的list;
- 判断是否相等,调用equals方法判断相等
- 判断是否需要进行扩容;
- 放入对象
hashmap成环的原因(JDK1.7以及之前的版本)
假设存在一个EntryList数据 A->B->NULL(后续补个图说明)
- 两条线程ThreadA&ThreadB进入对Map执行put方法插入数据C,发现此时map已经达到容量阈值
- 假设ThreadA优先执行,执行扩容,指针指向第一个元素A,准备开始采用头插法向新map迁移
- ThreadB开始执行,同样指针指向第一个元素A;
- ThreadA,开始头插法,新map中存在B->A->NULL(假设Hash结果所有数据还是路由到同一个entryList当中)
- ThreadB开始执行,同样持有元素A引用,往同一个新map插入,执行头插法,A->B-A(环的形成)
并发的扩容,头插法,操作同一个新map,数据路由到新map的同一个节点上,四个条件导致了成环的问题
hashmap为什么线程不安全
hashmap没有加锁,put方法线程并发会出现数据覆盖,导致前置数据丢失;并发产生的扩容操作会导致hashmap成环,导致get方法执行时陷入死循环。
hashmap在JDK1.8之后的变化
(1)JDK1.8引入了红黑树
(2)JDK1.8将头插法换成尾插法 (解决了成环的问题)
(3)JDK对hash算法做了升级,亦或操作,找位置使用的
HashSet
1 hashset底层实现
HashSet的底层实现就是HashMap,使用了虚拟的valueObject对象
TreeMap
TreeMap的底层实现原理
Tree底层采用红黑树来实现 第一:构建排序二叉树,第二:平衡二叉树
List
ArrayList
ArrayList动态数组,初始10,扩容1/2,轮流拷贝,读大于写
LinkedList
LinkedList底层是双向队列,读取效率低,适合写大于读,无初始,无扩容
CopyOnWriteArrayList
CopyOnWriteArrayList实现原理(双内存) 初始化单个容器,共享读,存在写入操作时Copy容器,写入阶段但读取数据的请求依然读取老的容器,写入完成进行引用覆盖。通过两块内存达到读写分离的效果。
ConcurrentHashMap(//todo, 待完善)
树
二叉查找树
左子树小于父节点,右字数大于父节点
平衡二叉树(AVL)
左字树和右子树高度之差<=1 B-树
平衡多路查找树(B树)
不是二叉树,n阶查找树,每一个节点存储升序的真正data信息或data所在节点的地址指针(升序二分查找),键值和data一一对应
B+树
平衡多路查找树的优化,叶子节点存储data数据,非叶子节点数据所在地址key
B+树如何实现范围查询
(1)B+树在叶子节点存储数据信息,非叶子节点存放有序的数据索引信息
(2)B+树满足左子树比当前节点小,右子树比节点大的特性
(3)找到范围查询的两个临界点的索引,索引的磁盘地址区间数据即是范围查询的结果
红黑树
- 节点是红色或者黑色
- 根节点是黑色
- 每个叶子的节点都是黑色的空节点(NULL)
- 每个红色节点的两个子节点都是黑色的。
- 从任意节点到其每个叶子的所有路径都包含相同的黑色节点。
小结
HashTable&HashMap&ConcurrentHashMap
HashMap: 线程不安全
HashTable:线程安全,采用Sychronied实现的同步操作
ConcurrentHashMap:分段可重入锁 线程安全
(1)JDK1.8引入了红黑树
(2)CAS+Sychronized换掉了可重入锁 锁细化了 Sychronized不升级成重量级别锁就不会影响效率
(3)JDK1.8将头插法换成尾插法
(4)JDK对hash算法做了升级,亦或操作,找位置使用的
ArrayList&LinkedList
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
- 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
- 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
B树&B+树
- 所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;
- 不可能在非叶子结点命中;
- 非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;
B+树的优势
B+树的磁盘读写代价更低,节点存储关键字主键更多 B+树的数据信息遍历更加方便,
遍历叶子节点就完成全遍历 B+树的查询效率更加稳定,直达叶子节点
B+树的缺点
缺点: 插入时,主键不是有序递增,插入数据产生大量的数据迁移和空间碎片
平衡二叉树&红黑树
红黑树,相比于平衡二叉树场景中对插入删除不频繁,只是对查找特别有要求,AVL还是优于红黑,红黑树,约束力比较弱的微平衡二叉树。最长路径不会是最短路径的两倍