目录
1. 泛型【相当于标签】
a. 声明类
b. 声明方法
c. 继承
d. 泛型约束
2. Iterable接口
3. collection接口【E元素存储】
A. List接口【不唯一,有序(底层为顺序表)】
a) ArrayList实现类
b) LinkedList实现类
B. Set接口【唯一,无序】
a) HashSet实现类
b) TreeSet实现类
c) comparator比较器
C. Queue接口【队列,FIFO】
4. Map接口【K-V存储】
A. HashMap实现类⭐⭐⭐
a) 基本原理
b) 重要属性(2和0.75)
c) Put数据进HashMap(流程)
B. TreeMap实现类
开始复习基础啦......
数组:长度确定后不可修改、增删效率低、声明后只能存一种类型。
集合:长度可变、增删效率高、声明后可存多种类型(除非指定泛型)、只能存引用类型。
1. 泛型【相当于标签】
在编译时进行了检查,添加、接收时要使用泛型制定的类型,对元素进行了限制。
a. 声明类
在类名后添加
泛型类的泛型类型在创建对象时指定,类中的static方法、属性优先于对象存在,先创建static再有对象,所以静态属性和方法不能使用定义在类上的泛型。
b. 声明方法
并非带泛型的方法都为泛型方法,泛型方法的泛型类型与类的泛型类型无关,即非泛型类也可有泛型方法。
泛型方法的泛型类型在方法调用时指定,所以泛型方法可以为静态方法。
c. 继承
父类指定泛型,子类无需指定,相当于参数类型已确定。父类没指定泛型,还是以class
如存在对象ArrayList
d. 泛型约束
使用通配符“?”号表示匹配任意类型,使用“? extends A”表示匹配类型为A的子类。
* 上界由extends指定:表示该类型必须是指定类型或其子类;
* 下界由super指定:表示该类型必须是指定类型或其父类;
加入通配符后可对List执行遍历、读取(用根类Object接收),不可进行add操作(为了防止乱加,直接给ban掉了)。
2. Iterable接口
ListIterator:继承于Iterator接口,只能用于各种List类型的访问。为解决iterator和List同时对集合操作发生并发修改异常,引入新的迭代器,迭代和添加操作均由ListIterator进行,可以判断next和previous,可进行逆向遍历。
首先,ArrayList是实现类,其他全为接口。
3. collection接口【E元素存储】
定义了基本的增、删、查、判断方法。equals比较的是内容,"=="比较的是地址。
A. List接口【不唯一,有序(底层为顺序表)】
相比于collection,多了可针对index操作的部分可使用索引。
创建对象的时候采用:接口 A=new 实现类; 的接口编程方式,可使代码更具有扩展性。
a) ArrayList实现类
底层实现:线性表(数组),紧密结构,两个重要属性->数组;大小
初始化大小为10,其对象为Object类型,数组满后开始扩容,新建一个大小为原数组1.5倍的数组,将原数组数据copy进去,数组引用指向新数组。
Jdk 1.8版本修改了调用空构造器时的操作:调用空构造器初始化为{},进行add操作时才创建一个长度为10的数组(grow方法增加-10 or 原数组长+原数组长/2[即使1.5倍扩容] )。——节省内存
比较Vector:扩容机制不同,为两倍扩容;为线程安全,synchronized修饰;效率低。(被淘汰)
b) LinkedList实现类
底层实现:线性表(双向链表),跳转结构。
使用index进行获取操作时,判断index和链表长度一半位置,决定从头开始找还是从尾部开始找。
B. Set接口【唯一,无序】
遍历方式为增强for循环(实现其实也是通过迭代器)和迭代器。
a) HashSet实现类
底层实现为hash表,即数组+链表。放入set的对象计算出hash值后,再计算出数组中的位置,再放入。放入set的对象需要重写hashCode和equals方法。
其实在调用HashSet构造器时,底层创建了一个HashMap对象,放入set的对象其实占了key的位置,value的位置放了一个final的Object对象。
b) TreeSet实现类
其底层原理同TreeMap,逻辑类似HashSet。即:HashSet=HashMap, TreeSet=TreeMap.
要想实现TreeSet的有序、唯一特性,放入set的对象一定要实现比较器。不实现比较器会报错,内部外部均可,外部比较器需作为参数传入构造器。
相比于HashSet就是增加了有序特性,由二叉树保证。
c) comparator比较器
分为内部比较器和外部比较器,内部比较器由类实现comparable接口并实现compareTo方法即可,外部比较器则重新定义一个类实现comparable接口,其作用就是一个专门用来比较的“工具”,然后创建set对象的时候作为参数传入。一般建议使用外部比较器,因为可实现多种比较规则。
C. Queue接口【队列,FIFO】
a) BlockingQueue【接口】阻塞队列
==>ArrayBlockingQueue、LinkedBlockingQueue等实现类;继承Queue接口。
使用情况:多线程并发处理,线程池。存在4组API。
b) BlockingDeque【接口】阻塞双端队列
继承Queue接口,继承双端队列接口+阻塞队列接口。
c) AbstractQueue【实现类】非阻塞队列
直接实现Queue接口。
d) SynchronizedQueue【实现类】
实现BlockingQueue接口,每个插入操作必须等待相应的删除操作由另一个线程,反之亦然,同步队列没有任何内部容量。类似于信号量的作用。
4. Map接口【K-V存储】
A. HashMap实现类⭐⭐⭐
a) 基本原理
原理:HashMap由数组+链表组成,即主体结构是数组,又叫hash桶数组,每个数组的元素是链表(为解决hash冲突),所以实为哈希表。
b) 重要属性(2和0.75)
主数组默认长度为16,后续扩容也需为,原因:
1. 以便后续对数组长度取余的时候,可以使用按位运算;
2. 数学原理上,更不易产生hash冲突
==>实际上是2倍扩容,对比ArrayList的1.5倍
扩容机制:
新建一个HashMap的底层数组,而后调用transfer方法,将就HashMap的全部元素添加到新的HashMap中(要重新计算元素在新的数组中的索引位置)。
static final float DEFAULT_LOAD_FACTOR = 0.75f; 默认加载因子为0.75
当容量被占到0.75倍时就需要ReSize扩容——当存储的数据一多,Entry内部的链表会很长。
//链表长度到8,就转为红黑树——降低查找深度 static final int TREEIFY_THRESHOLD = 8;
// 树大小为6,就转回链表 static final int UNTREEIFY_THRESHOLD = 6;
c) Put数据进HashMap(流程)
put元素时有两种情况,key值相同 & key值不同。
[1]. 相同:更新HashMap中已有的键值对,即更新key对应的value,如1:hello已存在,put 1:bye的时候,里面放的1:bye,1实为hello的1。
[2]. 不同:首先计算hashCode,然后根据hashCode计算数组的下标未知,位置为空就放进去,不为空就加入链表后。
计算hashCode的时候,采用了一个数学算法,然后进行了二次散列+一个扰动函数换算。
--->增加值的不确定性。
头插法是大于7就转为红黑树,小于7就转为链表。
B. TreeMap实现类
Tree一定要实现比较器,TreeSet和TreeMap都是。
集合的工具类Collections,类似数据的Arrays工具类,提供很多方法。
学习视频及部分截图来源:
B站马士兵说:【完结版】马士兵、赵珊珊2021Java零基础入门到精通400集(已完结)



