1.对象数组的内存图解
![](https://i-blog.csdnimg.cn/blog_migrate/f34d65856e7105113df7b2c2e987cf8d.png)
2.集合概述
集合的由来:
我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储。
而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的变量,在我们目前所学过的知识里面,有哪些是容器类型的呢?
数组和StringBuffer。但是呢?StringBuffer的结果是一个字符串,不一定满足我们的要求,所以我们只能选择数组,这就是对象数组。
而对象数组又不能适应变化的需求,因为数组的长度是固定的,这个时候,为了适应变化的需求,Java就提供了集合类供我们使用。
3.数组和集合的区别?
A:长度区别
数组的长度固定
集合
长度可变
B:内容不同
数组存储的是同一种类型的元素
而集合可以存储不同类型的元素
C:元素的数据类型问题
数组可以存储基本数据类型,也可以存储引用数据类型
集合
只能存储引用类型
3.集合的继承体系图解
![](https://i-blog.csdnimg.cn/blog_migrate/6d63ce105f467e0350c9c1d67b4275df.png)
4.Collection
Collection:是集合的顶层接口,它的子体系有重复的,有唯一的,有有序的,有无序的。
Collection的
功能概述:
1:添加功能
boolean add(Object obj):添加一个元素
boolean addAll(Collection c):添加一个集合的元素
2:删除功能
void clear():移除所有元素
boolean remove(Object o):移除一个元素
boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有)
3:判断功能
boolean contains(Object o):判断集合中是否包含指定的元素
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(是一个还是所有)
boolean isEmpty():判断集合是否为空
4:获取功能
Iterator<E> iterator()(重点)
5:长度功能
int
size():元素的个数
面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
6:交集功能
boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?
7:把集合转换为数组
Object[] toArray()
5.重点注意几个All方法
boolean addAll(Collection c):添加一个集合的元素
boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有)
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(只有包含
所有的元素,才叫包含)
boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?
addAll示例
![](https://i-blog.csdnimg.cn/blog_migrate/eb23a5e174a8fc8acbf805b8e1c5464d.jpeg)
removeAll示例(只要有一个元素被移除了,就返回true)
![](https://i-blog.csdnimg.cn/blog_migrate/82d250abd8b2594b65f07543eef01084.jpeg)
注意
boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?
//假设有两个集合A,B。
//A对B做交集,最终的结果保存在A中,B不变。
//
返回值表示的是A是否发生过改变。
![](https://i-blog.csdnimg.cn/blog_migrate/445e9f183c1c290924cc95643ba56144.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/524ab6657dc4dea807ecb6f21c6f95a6.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/76a41cba4ac5555f2dfefe6d7115bd69.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/26921c199ec198486e3aa37909a781b9.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/27213582096ed9299aafc040359a35fa.jpeg)
返回值表示的是A(原集合)是否发生过改变。
![](https://i-blog.csdnimg.cn/blog_migrate/b648b473660b76bfc69c16f42dfebab9.jpeg)
6.集合的遍历
集合的遍历,其实就是依次获取集合中的每一个元素。
Object[] toArray():把集合转成数组,可以实现集合的遍历
// 创建集合对象
Collection c = new ArrayList();
// 添加元素
c.add("hello"); // 这个语句隐含有Object obj = "hello"; 向上转型
c.add("world");
c.add("java");
// 遍历
// Object[] toArray():把集合转成数组,可以实现集合的遍历
Object[] objs =
c.toArray();
for (int x = 0; x < objs.length; x++) {
// System.out.println(objs[x]);
// 我知道元素是字符串,我在获取到元素的的同时,
还想知道元素的长度。
// System.out.println(objs[x] + "---" + objs[x].length());
// 上面的实现不了,原因是
Object中没有length()方法
// 我们要想使用字符串的方法,就必须把元素还原成字符串
//
向下转型
String s =
(String) objs[x];
System.out.println(s + "---" + s.length());
7.集合的遍历案例(最原始的遍历方式,以后不常用,用迭代器取代)
练习:用集合存储5个学生对象,并把学生对象进行遍历。
*
* 分析:
* A:创建学生类
* B:创建集合对象
* C:创建学生对象
* D:把学生添加到集合
* E:把集合转成数组
* F:遍历数组
public class StudentDemo {
public static void main(String[] args) {
// 创建集合对象
Collection c = new ArrayList();
// 创建学生对象
Student s1 = new Student("林青霞", 27);
Student s2 = new Student("风清扬", 30);
Student s3 = new Student("令狐冲", 33);
Student s4 = new Student("武鑫", 25);
Student s5 = new Student("刘晓曲", 22);
// 把学生添加到集合
c.add(s1);
c.add(s2);
c.add(s3);
c.add(s4);
c.add(s5);
// 把集合转成数组
Object[] objs = c.toArray();
// 遍历数组
for (int x = 0; x < objs.length; x++) {
// System.out.println(objs[x]);
Student s = (Student) objs[x];
System.out.println(s.getName() + "---" + s.getAge());
}
}
}
所需的同一个包下的Student类如下
![](https://i-blog.csdnimg.cn/blog_migrate/ef4dc6a4ebe0ad7e71d434816e67aa6f.jpeg)
8.Iterator迭代器
![](https://i-blog.csdnimg.cn/blog_migrate/cfe85e7d025afdc4f0cc2dc7f5ccb5d2.jpeg)
Iterator iterator():迭代器,集合的专用遍历方式
Object next():获取元素,并移动到下一个位置。
boolean hasNext():如果仍有元素可以迭代,则返回 true。
典型写法
Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator it = c.iterator(); // 实际返回的肯定是子类对象,
这里是多态。
while (it.hasNext()) {
// System.out.println(it.next());//这个其实也可以
String s =
(String) it.next();//建议
向下转型
System.out.println(s);
}
9.注意事项
![](https://i-blog.csdnimg.cn/blog_migrate/58d908d98ed3757e3568adb50f4256f3.jpeg)
10.迭代器使用图解和原理解析
![](https://i-blog.csdnimg.cn/blog_migrate/d52b2c5723c2185bb1b151aa53690557.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/d8bcc03b3b32c925351845de927e194f.png)
迭代器的源码 Iterator
Iterable Collection都是接口
![](https://i-blog.csdnimg.cn/blog_migrate/982de34b4999cc8199102397717feecc.png)
public interface Iterator {
boolean hasNext();
Object next();
}
public interface Iterable {
Iterator iterator();//这个方法到这里还没有实现
}
public interface Collection extends
Iterable {
Iterator iterator();//这个方法到这里还没有实现
}
public interface List extends Collection {
Iterator iterator();//这个方法到这里还没有实现
}
public class ArrayList
implements List {
public Iterator iterator() {
return
new Itr();//这个方法到这里开始实现
}
private class Itr implements Iterator {
public boolean hasNext() {}
public Object next(){} //直到这里上面的接口方法才算真正实现了
}
}
Collection c = new ArrayList();
c.add("hello");
c.add("world");
c.add("java");
Iterator it = c.iterator();
//new Itr();
while(it.hasNext()) {
String s = (String)it.next();
System.out.println(s);
}
11.List接口概述
有序的
collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
与
set 不同,列表通常允许重复的元素。
12.List集合的特有功能:
A:添加功能
void add(int index,Object element):在指定位置添加元素
B:获取功能
Object get(int index):获取指定位置的元素
C:列表迭代器
ListIterator listIterator():List集合特有的迭代器
D:删除功能
Object remove(int index):根据索引删除元素,
返回被删除的元素
E:修改功能
Object set(int index,Object element):根据索引修改元素,
返回被修饰的元素。
13.ListIterator特有功能
![](https://i-blog.csdnimg.cn/blog_migrate/623bc850a4a27de3c391a827c7a970e5.png)
public class ListDemo4 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
L
istIterator lit = list.listIterator();
while (
lit.hasNext()) {
String s = (String)
lit.next();
System.out.println(s);
}
System.out.println("----");
while (
lit.hasPrevious()) {
String s = (String)
lit.previous();
System.out.println(s);
}
}
}
14.一个需要注意的问题
问题
我有一个集合,如下,请问,我想
判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
按常理做法结果如下
![](https://i-blog.csdnimg.cn/blog_migrate/4c9c5307f89f4b13c91149d84817c4bf.png)
运行有异常
![](https://i-blog.csdnimg.cn/blog_migrate/e80c40563251cc75a1731fc41c43525c.png)
ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
产生的原因:
迭代器是依赖于集合而存在的,在判断成功后,
集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
其实这个问题描述的是:
迭代器遍历元素的时候,通过集合是不能修改元素的。
如何解决呢?
A:
迭代器迭代元素,
迭代器修改元素
元素是跟在刚才迭代的元素后面的。
B:
集合遍历元素,
集合修改元素(普通for)
元素在最后添加的。
附:接口 ListIterator<E>有如下几个方法(迭代器修改元素)
方法1如图
注意javaee被添加的位置
元素是
跟在刚才迭代的元素后面的
方法2如图
![](https://i-blog.csdnimg.cn/blog_migrate/c680e4127f28b472d4ca8cf37bab009a.png)
注意javaee被添加的位置
元素在最后添加的。
15.数据结构
数据结构:数据的组织形式
面试题:
常见的数据结构的优缺点?
(数据结构+算法)
16.List的子类特点
List:(面试题List的子类特点)
ArrayList:
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。
Vector:
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。
LinkedList:
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。
List有三个儿子,我们到底使用谁呢?
看需求(情况)。
要安全吗?
要:Vector(即使要安全,也不用这个,后面有替代的)
不要:ArrayList或者LinkedList
查询多:ArrayList
增删多:LinkedList
day15补充
集合的继承体系结构?
由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,
我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。
Collection
|--List
|--ArrayList
|--Vector
|--LinkedList
|--Set
|--HashSet
|--TreeSet