一 概述
集合是一种容器,用来装数据的,类似数组,但集合的大小可变,开发中也非常常用
Collection代表单列集合,每个元素(数据)只包含一个值.
Map代表双列集合,每个元素包含两个值(键值对).
Collection List Set 都是接口
ArrayList 与LinkedList为List接口的 实现类
HashSet和TreeSet 为Set接口的 实现类
二 Collection常见方法以及其子类增添方法
collection子类中有List集合与Set集合,由于Set无索引,List有索引
所以在List集合下增加了 关于指定索引的增删改查方法
LinkedList是基于双链表实现的,增加了头尾的增删查方法.
三 迭代器
迭代器是用来遍历集合的专用方法(数组没有迭代器),在Java中迭代器的代表是Iterator(单列集合专用遍历方式)
三 增强for循环
增强for中修改数据,不会印象数据源
增强for可以用来遍历集合或者数组
增强for遍历集合,本质就是迭代器遍历集合的简化写法
增强for遍历数组,底层是普通for循环逻辑
Lambda表达式方式遍历集合
并发修改异常
使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误.
由于增强for循环遍历集合就是迭代器遍历集合的简化写法,因此,使用增强for循环遍历集合,又在同时删除集合中的数据时,程序也会出现并发修改异常的错误
解决方法
迭代器:用迭代器自己的删除方法删除数据即可
增强for循环:暂时无法解决
普通for循环:可以单着遍历并删除,或者从前往后遍历,但删除元素后做i--操作
四 ArrayList集合的底层原理
基于数组实现的
查询速度快(注意:是根据索引查询数据快):查询数据同过地址值和索引定位,查询任意数据耗时相同.
删除效率低:可能需要把后面的很多数据进行前移
添加效率低:可能需要把后面很多的数据后移,再添加元素,或者也可能需要进行数组的扩容
Array集合的底层原理
1.利用无参构造创建的集合,会在底层创建一个默认长度为0的数组
2.添加第一个元素时,底层会创建一个长度为10的数组 elementDate
3.存满时,会扩容1.5倍
4.如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度一实际为准
ArrayList集合适合的应用场景
1.ArrayList适合:根据索引查询数据,比如根据随机索引取数据(高效),或者数据量不是很大时
2.ArrayList不适合:数据量大的同时,又要频繁的进行增删操作
五 LinkedList集合的底层原理
基于双链表实现的
链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址.
特点:查询慢,增删相对较快,但对首尾元素进行增删改查的速度是极快的.
LinkedList应用场景
1.设计队列
两端开口,先进后出
2.用来设计栈
一段开口,先进后出
六 Set集合
哈希值
就是一个int类型的数值,Java中每个对象都有一个哈希值
Java中的所有对象,都可以调用Object类提供的hashCode方法,返回该对象自己的哈希值
对象哈希值的特点
同一对象多次调用hashCode()方法返回的哈希值是相同的
不同对象,它们的哈希值一般不相同,但也可能会相同(哈希碰撞)
Object的hashCode方法根据"对象地址值"计算哈希值
子类重写后的hashCode方法可以根据对象属性计算哈希值
HashSet集合判定两个对象的标准就是两个对象的hash值是否一致,因此我们经常重写hashcode实现集合中对象去重
案例
七 HashSet集合的底层原理
基于哈希表实现
哈希表是一种增删改查数据,性能都较好的数据结构
哈希表
JDK8之前,哈希表=数组+链表
JDK8之后,哈希表=数组+链表+红黑树
HashSet集合利用哈希表操作数据的详细流程
1.创建一个默认长度16的数组,默认加载因子为0.75,数组名table
2.使用元素的哈希值对数组的长度求余计算出应存入的位置
3.判断当前位置是否为null,如果是null直接存入
4如果不为null,表示有元素,则调用eqauls方法比较
相等,则不存;不相等,则存入数组
JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树
JDK 8之前,新元素存入数组,占老元素位置,老元素挂下面
JDK 8开始之后,新元素直接挂在老元素下面
八 树结构
九 LinkedHashSet 底层原理
LinkedHashSet是不可重复的,存取有序的,底层是基于哈希表(数组、链表、红黑树)实现的
但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置
十 TreeSet
特点:不重复、无索引、可排序(默认升序排序,按照元素的大小,由小到大排序)
底层是基于红黑树实现的排序
注意
对于数值类型:Integer ,Double,默认按照数值本身的大小进行升序排序
对于字符串类型:默认按照首字符的编号升序排序。
对于自定义类型如Teacher对象,TreeSet默认是无法直接排序的
自定义排序规则
TreeSet集合储存自定义类型的对象时,必须指定排序规则,支持如下两种方式来指定比较规则。
方式一:自然排序
让自定义的类(如教师类)实现Comparable接口,重写里面的compareTo方法来指定比较规则
方式二:比较器排序
通过调用TreeSet集合有参构造器,可以设置Comparator对象(比较器对象,用于指定比较规则).