## 一. 对象数组的概述和使用
1. **案例演示**
* 需求: 创建5个学生对象, 将对象存入到数组中,遍历数组,打印学生信息
```java public static void main(String[] args) { Student[] sts = new Student[5]; sts[0] = new Student("小红", 18); sts[1] = new Student("小明", 19); sts[2] = new Student("小白", 20); sts[3] = new Student("小辉", 21); sts[4] = new Student("小张", 23); for (int i = 0; i < sts.length; i++) { System.out.println(sts[i]); } } ```
2. 解析
* 数组中存放的是对象的地址值
* 遍历数组时就可以拿到引用地址值,调用对象完成方法
## 二. 集合概述
1. 概述
* 我们都知道,数组的长度是不可变的, 当元素的个数超过数组的长度之后, 我们就只能通过创建长度更长的新数组的方式来存储元素, 太麻烦了
* 集合给我提供另外一种容器的概念,可变长度的容器, 这样,程序在使用的时候就不需要再考虑容器容量的问题,从而可以更加专心于业务
* 我们要知道,java中数组是唯一的底层容器,所有, 集合是开发者使用java规范制作的逻辑上的容器
2. 数组和集合的区别
* 区别1
* 数组既可以存储基本数据类型, 又可以储存引用数据类型,基本数据类型存储的是值, 引用数据类型储存的是地址值
* 集合只能存储引用数据类型(对象的引用), 其实集合也可以存储基本数据类型, 但是在存储的时候自动装箱变成包装类对象
* 区别2
* 数组长度是固定的,不能自动增长
* 集合的长度的是可变的,可以根据元素的增加而增长
3. 使用场景
* 如果元素的个数是固定的,推荐使用数组
* 如果元素的个数不固定,推荐使用集合(日常开发中,使用集合比较普遍)
5. 集合分类
* Collection集合
* 单列集合, 直接存储对象的引用
* Map集合
* 双列集合, 使用key-value的形式, 每个元素会有一个唯一的名称
## 三. Collection集合
1. 定义
* Collection是单列集合, 用于存储单个元素
* Collection是一个接口, 他的下面有多个子接口和实现类, 我们称之为Collection体系
2. 分类
* List 集合中的元素是有序的,可以存放重复元素
* Queue 队列, 除优先级外, 保持先进先出的原则(基本不用)
* Set 集合中的元素是无序的, 不能存放重复的元素
4. 常用方法
* boolean add(E e) 添加元素
* boolean remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话
* void clear() 移除此 collection 中的所有元素
* boolean contains(Object o) 判断集合中是否包含指定元素
* boolean isEmpty() 判断集合中元素的个数是否为空
* int size() 获取集合中元素的个数
5. 案例演示
```java public static void main(String[] args) { //如果没有泛型,会报出警告,不影响运行 Collection collection = new ArrayList<>(); Student student1 = new Student("小红", 18); Student student2 = new Student("小明", 19); collection.add(student1);//添加方法 collection.add(student2); //判断集合中是否包含某个元素 System.out.println(collection.contains(student1));//结果为 : true //判断集合中元素的个数是否为null System.out.println(collection.isEmpty());//结果: false //获取集合中元素的个数 System.out.println(collection.size());//结果为 : 2 //移除某个元素 System.out.println(collection.remove(student2));//结果:true System.out.println(collection.size());//结果: 1 //清空集合中的元素 collection.clear(); System.out.println(collection.size());//结果为0 } ```
6. 集合中所有带All的方法
* boolean addAll(Collection c)将指定 collection 中的所有元素都添加到此 collection 中
* boolean removeAll(Collection c) 移除此 collection 中那些也包含在指定 collection 中的所有元素
* boolean containsAll(Collection c) 判断此 collection 是否包含指定 collection 中的所有元素
* boolean retainAll(Collection c) 仅保留此 collection 中那些也包含在指定 collection 的元素
* 演示
```java public static void main(String[] args) { Collection collection = new ArrayList<>(); Student student1 = new Student("小红", 18); Student student2 = new Student("小明", 19); collection.add(student1);//添加方法 collection.add(student2); Collection collection2 = new ArrayList<>(); Student student3 = new Student("小辉", 18); collection2.add(student1); collection2.add(student3); //将collection2集合中的元素添加到collection集合中 collection.addAll(collection2); System.out.println(collection.size());//结果: 4 //判断collection集合中是否包含collection2集合中的所有元素 boolean flg = collection.containsAll(collection2); System.out.println(flg);//结果: true //仅在collection中保留两个集合中相同的元素 collection.retainAll(collection2); System.out.println(collection.size());//结果: 3 } ```
## 四. 迭代器
1. 定义
* 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)
2. 案例演示遍历集合
```java public static void main(String[] args) { Collection collection = new ArrayList<>(); Student student1 = new Student("小红", 18); Student student2 = new Student("小明", 19); Student student3 = new Student("小辉", 18); collection.add(student1);//添加方法 collection.add(student2); collection.add(student3); //集合转数组进行遍历 Object[] obs= collection.toArray(); for (int i = 0; i < obs.length; i++) { System.out.println(obs[i]); //前提集合内的元素重写了toString()方法 } } ```
3. 迭代器的遍历形式
* 步骤
* 获取迭代器
* 调用hashNext()方法判断下一个元素是否存在
* 调用next()方法获取元素
* 演示
```java public static void main(String[] args) { Collection collection = new ArrayList<>(); Student student1 = new Student("小红", 18); Student student2 = new Student("小明", 19); Student student3 = new Student("小辉", 18); collection.add(student1);//添加方法 collection.add(student2); collection.add(student3); //for循环的形式 for(Iterator it = collection.iterator();it.hasNext();){ Student student = it.next(); System.out.println(student); } //while循环的形式 Iterator it = collection.iterator(); while(it.hasNext()){ Student student = it.next(); System.out.println(student); } } ```
4. 迭代器工作原理
* Iterator是一个接口,规定了迭代器的基本使用, 集合的子类都实现了迭代器方法, 同时返回属于自己的迭代器对象
* 迭代器相当于是集合的一个副本, 里面记录了集合的基本属性值.
* 使用时,我们先调用hashNext方法判断是否有下一个元素,如果有则返回true,否则返回false
* 然后调用next()方法,返回当前指针所在位置上的元素
5. 修改集合导致的异常
* 当我们使用迭代器遍历集合的时候,如果对集合(使用集合的方法)进行了修改,下一次循环会报错
* 原因: 集合会记录修改的次数, 如果迭代器发现集合副本和原集合修改次数不一样的话就会报错
* 解决办法: 使用迭代器的删除方法(就可以删除集合里的元素了)
* 演示
```java public static void main(String[] args) { Collection collection = new ArrayList<>(); Student student1 = new Student("小红", 18); Student student2 = new Student("小明", 19); collection.add(student1);//添加方法 collection.add(student2); //while循环的形式 Iterator it = collection.iterator(); while(it.hasNext()){ Student student = it.next(); //collection.remove(student); it.remove(); } } ```
## 五. List集合
1. 定义
* List集合是有序的,可以储存重复的数据
* List集合通过记录元素在集合中的位置来准确的查找元素
2. List集合体系
* ArrayList 底层使用数组(线程不安全)
* LinkedList 底层使用链表
* Vector 底层使用数组(线程安全的,不推荐使用)
## 六. ArrayList集合
1. 定义
* 低层使用的是数组, 所以其特性非常接近于数组
* 储存的元素是有序的,而且可以重复存储, 通过数组角标来查询更改元素,速度非常快
* 由于每次增删都要改动数组中的角标,所有导致增删效率低下
2. ArrayList的增删改查原理
* ArrayList 集合初始化会有一个默认长度是10的数组, 内部还有一个记录当前元素个数的变量, 当储存的元素个数超过数组长度之后,容量就会扩充一半
* 当我们去查询集合中的元素时, 需要提供给集合一个角标值, 然后通过这个角标值查找集合中的元素
* 当我们去删除一个元素的时候, 集合就会根据角标删除这个元素,并且改动其他元素的位置,这就是导致增删缓慢的原因
* 其实如果我们是连续往集合尾部插入数据的话, 速度其实是非常快的, 因为其他元素的位置不需要改动,但是如果我们插入数据的位置是数组的前面或者中间,速度就会有明显的降低
3. 构造方法
* ArrayList() 构造一个初始化容量为10的空列表
* ArrayList(Collection exends E> e) 构造一个包含执行集合元素的列表
* ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表
4. 常用方法
* boolean add(E e) 将指定的元素添加到此列表的尾部
* void add(int index,E element) 将指定的元素插入此列表中的指定位置
* boolean contains(Object o) 如果此列表中包含指定的元素,则返回true
* get(int index) 通过角标查找元素
* int indexOf(Object o) 返回此列表中首次出现的指定元素的索引(从前往后查), 或如果没有则返回 -1
* int lastIndexOf(Object o) 返回此列表中最后一次出现的指定元素的索引(从后往前查)没有返回-1
* boolean remove(Object o) 移除此列表中首次出现的指定元素(如果存在)
* E set(int index , E element) 用指定元素替代此列表中指定位置上的元素,返回原来的元素
* int size() 返回此列表中的元素数
5. 演示
```java public static void main(String[] args) { ArrayList list = new ArrayList<>(); //添加元素 list.add("小红"); list.add("小明"); //将元素添加到角标1上 list.add(1,"小辉"); System.out.println(list.contains("小明"));//true //通过角标获取 String str = list.get(1); System.out.println(str);//结果: 小辉 //通过元素获取角标 System.out.println(list.indexOf("小明"));//结果 : 2 //通过角标移除元素 System.out.println(list.remove(1));//结果: true //通过角标设置元素 System.out.println(list.set(1, "小李"));//小辉 } ```
6. ArrayList集合的遍历
* for 循环遍历, 基本上等同于数组
* 演示
```java public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add("小红"); list.add("小明"); list.add("小辉"); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } ```
* 迭代器 使用公用迭代器
* 演示
```java public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add("小红"); list.add("小明"); list.add("小辉"); Iterator it = list.iterator(); while (it.hasNext()) { String str = it.next(); System.out.println(str); } } ```
* 迭代器2 List集合的迭代器(ListIterator) 可以从后往前遍历
* 演示
```java public static void main(String[] args) { ArrayList list = new ArrayList<>(); list.add("小红"); list.add("小明"); list.add("小辉"); ListIterator it = list.listIterator(); while (it.hasNext()) { String str = it.next(); System.out.println(str); } while(it.hasPrevious()){ String str = it.previous(); System.out.println(str); } } ```
## 七. LinkedList集合
1. 定义
* 底层使用的是链表,就好像一条锁链
* 这个集合中的每个元素都被封装到一个叫Node的内部类中, 然后记录上一个元素和下一个元素的地址,通过手拉手形成一个链条
* 增删快, 查询慢
2. 增删改查的原理
* 当需要去查询LinkedList集合中的元素时,需要从最开始的元素查找起,然后一层一层往后找,直到找到该元素,这样的动作十分消耗性能
* 当需要去删除元素的时候, 我们只需要将被删除元素两端的元素重新连接到一起,或者新增的时候将新元素和左右两边的元素连起来就可以了
3. 构造方法
* LinkedList() 构造一个空列表
* LinkedList(Collection extends E> e) 构造一个包含指定collection中元素的列表
4. 常用方法
* E remove() 获取并移除此列表的头
* E poll() 获取并移除此列表的头
* E peek() 获取但不移除此列表的头
5. 演示
```java public static void main(String[] args) { LinkedList list = new LinkedList<>(); list.add("小红"); list.add("小明"); list.add("小辉"); System.out.println(list.remove());//结果: 小红 System.out.println(list.size());//结果:2 System.out.println(list.poll());//结果: 小明 System.out.println(list.size());//结果:1 System.out.println(list.peek());//结果: 小辉 System.out.println(list.size());//结果:1 } ```
## 八. ArrayList, LinkedList 及Vector集合之间的区别
1. 线程安全
* Vector : 线程安全
* ArrayList, LinkedList : 线程不安全
2. 实现方式
* LinkedList : 链表
* ArrayList,Vector : 数组
3. 扩容
* ArrayList和Vector使用数组实现, 当数组长度不够,内部会创建一个更大的数组
* LinkedList 不存在这方面的问题
4. 速度
* ArrayList 查改块, 增删慢
* LinkedList 查改慢, 增删快