DAY31
1.为什么需要集合类
很多情况下,我们需要对一组对象进行操作,而且很可能事先并不知道到底有多少个对象。为了解决这个问题,Java就提供了集合类供我们使用。
2.集合类的特点
a.只能存储引用类型的数据
b.可以自动的调整自己的大小
3.数组和集合类都是容器,它们有何不同
a.数组可以存储基本数据类型的数据,集合不可以
b.数据的长度是固定的,集合可以自动调整自己的大小
c.数组的效率高,相对来说集合效率比较低(因为使用集合就需要调用他一些方法,调用方法就需要出栈入栈等等)
d.数组没有API(java中没有对应的数组类,都是jvm自动生成的,因此是没有API),集合有丰富的API
对于集合只有增删查,没有改
collection
概述:
Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
集合类的特点:
a.容量可变
b.只能储存引用数据类型
JDK5特性:自动装箱和自动拆箱
API:
增:
boolean add(E e)----(E表示泛型)
boolean addAll(Collection c)-----添加一个集合----如果集合发生了改变返回true,否则false
删:
void clear()
boolean remove(Object o)---删除与指定对象o相等的元素
boolean removeAll(Collection c)
boolean retainAll(Collection c)----保留c中存在的元素
查:
boolean contains(Object o)----是否包含与指定对象o相等的元素
boolean containsAll(Collection c)----c集合中的元素是否都在当前集合中存在
获取集合的属性:
boolean isEmpty()
int size()---集合中元素个数
遍历:
迭代器:提供遍历的操作
因为toCharry满足不了需求,引入了Iterator()(迭代器)
Iterator iterator();
Iterator it = c.iterator();//获取一个迭代器
问题:
集合转化成数组:Collection : toArray()
数组如何转化成为集合?---工具类
关于Object[] toArray()----将这个集合转化为数组,不改变原来的集合(额外复制了一份)
cursor:下一个元素的索引位置
cursor的取值范围:[0,size()]
cursor指向的是两个元素之间的位置,而不是直接指向元素,所以是左闭右闭
Iterator:
a.boolean hasNext()---仍有元素可以迭代
b.next()
c.void remove()---删除最近返回的元素---对集合产生了修改
Iterator原理
1.为什么Iterator要定义成一个接口,而不是一个类?
不同的集合底层的数据结构不一样的,遍历的方式自然也就不一样。因此,我们不能定义成一个普通类。但是,所有的集合都应该提供遍历的操作,我们应该提供一个统一的 标准
2.在Java中什么表示“标准”呢?
抽象方法
3.为什么不定义成抽象类,而定义成接口呢?
集合不是迭代器,因此不用继承
但是集合应该具有迭代的功能,所以定义成接口,iterator不能定义成抽象类
4.Iterator it = c.iterator();获取的是哪一个子类的对象呢?
5.迭代器遍历的是谁的数据?
迭代器必须知道集合底层的数据结构。
(类有三大特性——封装继承多态)
封装是为了不让外界知道底层的 数据结构,但是集合的数据结构应该是私有的
一个类怎么访问另一个类的私有成员?
内部类
6.迭代器应该设计成内部类的形式(反射虽然功能强大,但是不建议使用),内部类有哪几种
静态内部类
成员内部类
局部内部类
匿名内部类
7.迭代器应该设计成哪一种形式的内部类?
局部内部类
对象的底层数据结构不是静态(静态表示这个类的所有对象共享的,例如集合c1和c2,不能共享底层的数据结构,所以不是静态内部类)
局部内部类——局部内部类只能在方法内使用,如果要在多个方法中生成迭代器,那么这个类要重写2次,为了避免这种现象存在,不用局部内部类
匿名内部类——一般情况匿名内部类是局部内部类的简化形式
————————————————————————————
成员内部类是外部类对象所有,成员内部类对象依赖外部类对象存在。
迭代器依赖外部类对象存在
Iterator it = c.iterator();------------外部类对象c
这就是迭代器设计模式(java中集合就是采用的迭代器设计模式)
——-------————————————————————————
并发修改异常(ConcurrentModification Exception)以及注意事项:
1.如果用集合的api修改了集合的结构,那么所有的迭代器都会失效
2.如果用迭代器的API修改了集合的结构,那么所有其他迭代器会失效(因为一个集合有多个迭代器,只是改变了自己的迭代器的光标的位置,而没改变其他的光标位置,所以会失效)
3.使用集合对象的时候,不要使用while循环,可以使用for循环,最好使用foreach循环(foreach循环有一定的局限性,只能查询不能修改)
while(it.hasNext()){ String s = (String)it.next(); System.out.println(s); } //改写为用迭代器的for循环 //for循环 //Iterator it = c.iterator()就是初始化语句 //it.hasNext()就是条件判断语句 //循环体语句中就已经体现出控制语句,所以条件控制语句省略了 for(Iterator it = c.iterator(); it.hasNext(); ){ String s = (String)it.next(); System.out.println(s); }