其实各种八股文资料,他也就是围绕着核心知识展开提问的,你只要根据八股文把核心知识提炼出来,形成核心知识体系!
Java集合那是重点中的重点。最基本的概念要懂,核心的概念,那要滚瓜烂熟。
Java集合俩大接口:Collection(子接口List、Set、Queue)、Map
掌握四个接口以及每个接口的重要实现类,再加上一些细节点。
有些压根就是看一下,但是重点就是那几个!!写下来,不断回看。
0、为啥要使用集合?
1、List、Set、Queue、Map区别?
2、集合底层数据结构说说
3、怎么选择合适的集合?
需要排序选择TreeMap,不需要就选HashMap,要求保证线程安全选ConcurrentHashMap
要求元素唯一(不可重复)选择Set接口下集合,TreeSet、HashSet,不要求就选ArrayList、LinkedList等
List = ArrayList + LinkedList
新容量 = 旧容量 * 1.5
触发扩容 -> 新开1.5倍容量 -> 复制 -> 清空原空间 -> 扩容中检查是否超出最大容量限制
分析时间复杂度,注意要分类讨论!
插入:
头插元素后移O(n);尾插不扩容O(1),扩容O(n);指定位插O(n)
删除:
头删前移O(n);尾删O(1);指定删O(n)
randomaccess接口是标记接口,表明实现该接口的类支持随机访问(通过索引快速访问元素),
LinkedList底层数据接口是双向链表,内存地址不连续只能通过指针索引,不能随机访问,所以不能实现randomaccess接口。
HashSet底层数据结构是哈希表(基于HashMap实现)查重时:
HashSet添加元素条件:哈希码不同;哈希码相同但equals方法返回false
实现Comparable接口要重写CompareTo(Object obj)方法,由自定义类内部实现排序方法;
实现Comaprator接口要重写Compare(Object obj1 , Object obj2)方法,由外部定义实现排序
重写Comparable接口的CompareTo方法:
public class Person implements Comparable {
......
@Override
public int compareTo(Person o) {
if (this.age > o.getAge()) {
return 1;
}
if (this.age < o.getAge()) {
return -1;
}
return 0;
}
}
重写Compare:
Collections.sort(arrayList);
// 定制排序的用法
Collections.sort(arrayList, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
Map = HashMap + TreeMap + ConcurrentHashMap
计算数组下标:
左侧一维数组,数组元素内容是指向另一个链式数组的指针。绿色部分是
hash表的工作原理:
HashMap基于哈希表的Map接口实现,存储键值对,支持快速插入删除查找;底层数据结构为数组 + 链表/红黑树
具体实现:
put()插入值:jdk1.8之前,底层为数组+链表。HashMap通过hashcode经过扰动函数处理得到hash值,再通过(Entry.length - 1)&hash得到元素存放位置,如果该位置存在元素,就判断该元素与要存入的元素的Key和哈希码hashcode是否相同,相同则直接覆盖,不相同,则通过拉链法解决哈希冲突;
jdk1.8之后,变化就是优化了解决哈希冲突,当链表长度大于阈值(8)这时会判断若当前数组长度小于64先进行数组扩容,不然就将链表转换成红黑树以减少搜索时间。
链表法:将链表和数组结合。创建一个链表数组,数组中每一格就是一个链表,若遇到哈希冲突,就将冲突的值加到链表中即可。
get()取出值也是类似的过程。
1、整体架构:与HashMap相同 数组 + 链表/红黑树
2、基本功能:在HashMap基础上增加了并发安全,并发安全的实现是通过对Node节点加锁来保证数据更新的安全性
性能优化:为了平衡并发性能与数据安全性,jdk1.8之前锁的粒度是segment,jdk1.8之后锁的粒度为Node节点,缩小锁的范围提高并发性能,引入多线程并发扩容
(多线程并发扩容:多个线程对原数组进行分片,分片后每个线程负责一个分片的数据迁移,从而提升扩容效率)