1.集合
集合:ArrayList 是一种容器,用来装数据的,类似于数组,但集合的大小可变,开发中也非常常用。
1.1体系概况
Collection集合体系:
特点:
List系列集合:有序、可重复 包括ArrayList; LinekdList.
Set系列集合:无序、不重复 包括HashSet; LinkedHashSet: 存取有序 ; TreeSet:可排序.
1.2Collection的常用方法
boolean add(E e) 添加元素 boolean remove(E e) 删除指定的元素 (如有重复删除第一个) boolean contains(Object obj) 判断集合中是否包含指定元素 int size() 返回集合中元素的个数 boolean isEmpty() 判断集合是否为空 Object[] toArray() 将集合中元素存入一个对象数组并返回 T[] toArray(T[]a) 将集合中元素存入一个指定类型的数组并返回(指定数组长度) void clear() 清空集合 void addAll(集合) 添加另外一个集合中的元素
1.3Collection的遍历方式
Collection的遍历方式有三种:
迭代器、增强for、Lambda
1.3.1迭代器:
迭代器是用来遍历集合的专用方式(数组没有迭代器),在Java中迭代器的代表是Iterator。
使用方法:
1.3.2增强for
1.3.3Lambda
经过Lambda化简后:
1.4Collection的并发修改异常
使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误。
由于增强for循环遍历集合就是迭代器遍历集合的简化写法,因此,使用增强for循环遍历集合,又在同时删除集合中的数据时,程序也会出现并发修改异常的错误
怎么保证遍历集合同时删除数据时不出bug?
使用迭代器遍历集合:但用迭代器自己的删除方法删除数据即可。
2.List集合
List集合因为支持索引,所以多了很多与索引相关的方法,不仅如此,List同时也继承了Collection的所有功能.
List集合支持的遍历方式: 1.迭代器 2.增强for循环 3.Lambda表达式 4.for循环(因为List集合有索引)
2.1List独特的方法
2.2ArrayList
ArrayList是基于数组实现的。
优点:
查询速度快(注意:是根据索引查询数据快)
缺点:
删除效率低:可能需要把后面很多的数据进行前移。
添加效率极低:可能需要把后面很多的数据后移,再添加元素;或者也可能需要进行数组的扩容。
2.2.1ArrayList的底层原理:
1.利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组
2.添加第一个元素时,底层会创建一个新的长度为10的数组
3.存满时,会扩容1.5倍
4.如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准
2.2.2ArrayList适合的业务场景
适合:根据索引查询数据.比如随机索引取数据或者数据量不是很大时
不适合:数据量大的同时又要频繁的进行增删查
2.3LinkedList
LinkedList是基于双链表实现的。
链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。
链表的特点:
链表的特点1:查询慢,无论查询哪个数据都要从头开始找。但对首尾元素进行增删改查的速度是极快的。
链表的特点2:链表增删相对快
LinkedList特有的方法:
LinkedList的应用场景之一:可以用来设计队列
先出先进,后出后进 常用于排队购票等
LinkedList的应用场景之一:可以用来设计栈
先进先出,后进后出 类似子弹上膛的原理
数据进入栈模型的过程称为:压/进栈(push)
数据离开栈模型的过程称为:弹/出栈(pop)
3.Set系列集合
特点:无序; 不可重复
包括:HashSet
LinkedHashSet:存取有序
TreeSet:可排序
(注意: Set要用到的常用方法,基本上就是Collection提供的!!)
3.1HashSet
哈希值:就是一个int类型的数值,Java中每个对象都有一个哈希值。
Java中的所有对象,都可以调用Obejct类提供的hashCode方法,返回该对象自己的哈希值。
public int hashCode():返回对象的哈希码值。
同一个对象多次调用hashCode()方法返回的哈希值是相同的。 不同的对象,它们的哈希值一般不相同,但也有可能会相同(哈希碰撞)。 Object的hashCode方法根据"对象地址值"计算哈希值 子类重写后的hashCode方法可以根据"对象属性值"计算哈希值
3.1.2Set集合去重复
创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合,要求:学生对象的成员变量值相同,我们就认为是同一个对象
实现步骤:
1.定义学生类,创建HashSet集合对象, 创建学生对象
2.把学生添加到集合
3.在学生类中重写两个方法,hashCode()和equals(),自动生成即可
hashCode()和equals()的重写(自动生成即可):
3.2HashSet集合的底层原理
基于哈希表实现。 JDK8之前,哈希表 = 数组+链表 ; JDK8开始,哈希表 = 数组+链表+红黑树
Hash是如何完成对象保存和去重的?
① 创建一个默认长度16,默认加载因为0.75的数组,数组名table
② 根据元素的哈希值跟数组的长度计算出应存入的位置
③ 判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素, 则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组.
④ 当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍
3.3LinkedHashSet
LinkedHashSet是不可重复的,存取有序的,底层是基于哈希表(数组、链表、红黑树)实现的。
但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置。
3.4TreeSet
特点:不重复、无索引、可排序(默认升序排序 ,按照元素的大小,由小到大排序)
底层是基于红黑树实现的排序。
注意:
对于数值类型:Integer , Double,默认按照数值本身的大小进行升序排序。
对于字符串类型:默认按照首字符的编号升序排序。
对于自定义类型如Teacher对象,TreeSet默认是无法直接排序的。
3.4.1自定义排序规则
TreeSet集合存储自定义类型的对象时,必须指定排序规则,支持如下两种方式来指定比较规则:
方式一:自然排序 让自定义的类(如教师类)实现Comparable接口,重写里面的compareTo方法来指定比较规则。
重写CompareTo方法:
方式二:比较器排序 通过调用TreeSet集合有参数构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)。