栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java基础-集合【超全超基础】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java基础-集合【超全超基础】

目录

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. 声明类

在类名后添加,如class G{},实例化时可指定G,如不声明,则E被当成Object对象-{泛型擦除}。

泛型类的泛型类型在创建对象时指定,类中的static方法、属性优先于对象存在,先创建static再有对象,所以静态属性和方法不能使用定义在类上的泛型。

b. 声明方法

并非带泛型的方法都为泛型方法,泛型方法的泛型类型与类的泛型类型无关,即非泛型类也可有泛型方法。

泛型方法的泛型类型在方法调用时指定,所以泛型方法可以为静态方法。

c. 继承

父类指定泛型,子类无需指定,相当于参数类型已确定。父类没指定泛型,还是以class 进行声明,子类必须为泛型类。

如存在对象ArrayList A,  ArrayList B,ArrayList C,A、B、C间为并列关系,虽然Object和String间存在继承关系,但作为泛型参数他们无继承关系,不能采用A=B、A=C这种方式进行赋值。

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集(已完结)

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号