一:集合的由来:
在面向对象的世界里,我们为了方便对多个对象进行操作,就必须把多个对象进行存储。想要存储多个对象,我们就需要一个容器,而不是单单的一个基本变量。目前我们知道数组和StringBuffer是带有容器性质的,但是,StringBuffer的结果是一个字符串,不一定 满足我们的需求,所以我们只能选择数组。但是数组的长度又是固定的,不能适应变化的需求,为了适应变化,这个时候Java就提供了集合类给我们使用。
- 那么数组和集合类有什么区别呢?
- 长度不同。数组的长度是固定的,但是集合的长度是可以变化的。
- 内容不同。数组存储同一种的元素,但是集合的元素可以是不同的。
- 元素的数据类型不同。数组既可存储基本类型也可以存储引用类型,但是集合只能存储引用类型。
- 既然集合是存储多个元素的,那么我们的需求肯定也是多元的。比如想要元素不能重复,想从小到大排列集合元素,针对不同的需求,Java给我们提供了不同的集合类,不同的集合类的数据结构不同。但是这不是很重要,重要的是这些类能够存储东西,不仅仅能存储,而且能够使用这些元素,比如判断、获取等等。既然这样,这些集合类肯定有共性的东西,我们把共性的东西不断的向上提取,就形成了集合类的继承结构体系。
- 数据结构:数据的存储方式。
用一个简单的图来表示集合的继承结构:我们可以从Collection开始学习,因为它的方法是共性的。
- Collection:是集合的顶层接口,它的子体系中有重复的,也有唯一的,有有序的,也有无序的。
- Collection的功能概述
-
- 添加功能
-
boolean add(Object obj):添加一个元素
-
boolean addAll(Collection c):添加一个集合的元素
-
- 删除功能
-
void clear():移除所有元素
-
boolean remove(Object o):移除一个元素
-
boolean removeAll(Collection c):移除一个集合的元素(是一个还是所有)
-
- 判断功能
-
boolean contains(Object o):判断集合中是否包含指定的元素
-
boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(是一个还是所有)
-
boolean isEmpty():判断集合是否为空
-
- 获取功能
-
Iterator<E> iterator()(重点)
-
- 长度功能
-
int size():元素的个数
-
面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
-
-
交集功能
-
boolean retainAll(Collection c):两个集合都有的元素?思考元素去哪了,返回的boolean又是什么意思呢?
-
-
把集合转换为数组
-
Object[] toArray()
-
- 添加功能
二、我们写代码来验证下上述的功能
- 验证add功能
- 验证clear功能
- 验证remove功能
- 验证size功能
- 验证addAll功能
- 验证removeAll功能
- 验证containAll功能
- 验证retainAll功能
三、那么我们如何遍历集合呢?
我们看到上面有一个功能是把集合变成数组,如果我们把一个集合变成了数组,那么我们对这个数组遍历就非常容易了,也就相当于遍历了集合。
如果我们把集合通过Object[] toArray的方法转成了数组,然后遍历,但是我们现在想要获取每个元素的长度怎么办呢?由于Object本身是没有length的方法的,所以我们不能直接使用length方法获取元素长度,这个时候我们需要把每个元素变成字符串,这样我们就能使用length方法了,那么我们怎么把数组的元素换成字符串呢。强制转型/String s = (String) objs[i]; 一旦转型成功,我们就能直接获取每个字符串的长度,相当于是数组中元素的长度。
四、那么我们怎么自定义对象并遍历这个集合呢?
五、Interator的使用
- 上面我们讲的遍历都不是最佳方法,在集合中Java专门用Interator()方法遍历集合
- 那我们自定义对象,用iterator遍历集合吧
思考:上面我们用while循环中遍历为什么我注释了System.out.println(it.next());这一行代码呢?
((Student)(it.next())).getName+((Student)(it.next())).getAge这种形式不要用,因为next会使用两次,我们直接用类转型接受打印就好了
思考题:为什么Java把iterator迭代器定义为一个接口而不是一个类?
假设迭代器是一个类,这样我们创建该类的对象调用该类的方法来遍历。但是,Java集合中有很多的集合类,这些类的数据结构是不同的,所以存储的方式是不同的,进而他们的遍历方式也应该是不一样的,最终没有定义为迭代器类。而无论是哪一种集合,都应该具备遍历功能,最好在辅助于判断功能,在获取前先判断,这样就更不容易出错,判断功能和获取功能应该是集合遍历所具备的。而每种集合遍历的方式不一样,所以我们把功能提取出来,并不提供具体实现,这种方式就是接口。
那么这种真正具体实现类又在哪里呢?在真正具体的子类中,以内部类的具体方式实现。