------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------
一、集合类
1、为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,有两种存储方式,一种是数组,一种是集合。集合是存储对象最常用的一种方式。
总结:数据多了,用对象存,对象多了,用集合存。
2、 数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象。
例如:我们无法确定员工的人数。
数组和集合还有一点不同:数组诞生的时候,就必须确定里面存储的类型,
而集合,只要是对象,都可以存储。
所以集合的应用领域更为广泛。
3、集合类的特点: 集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象
4、集合框架概念
容器:有很多种容器类型。Java对容器进行了不同的划分。并且发现不同容器都有共性的部分,就按照面向对象的思想向上抽取,形成了一个体系。我们称之为集合框架。
二、Collection
1、关系图
我们还是先了解顶层。因为顶层都是定义的是最共性的内容,最基本的内容。 顶层的部分就叫做Collection 集合的意思。位于java.util包中。
查阅api文档,我们发现collection已经被定义为接口。
这个接口中定义了许多子接口。我们重点学习其中的两个,一个是List,一个是Set
Collection
|------List|
|-----ArrayList
|-----LinkedList
|------Vector
|------Set
|-----HashSet
|------TreeSet
........
为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式都有不同。这个存储方式,我们称之为数据结构。
Collection是根接口,此接口是集合框架中的一个成员。
2、常用方法
1) 增加操作
boolean add(E e) 确保此collection包含指定的元素
boolean addAll(Collection<? extends E> c)
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
意思就是能添加一组元素。
2)删除操作
void clear() 清空
移除此 collection 中的所有元素
3)判断操作
boolean remove(Object o)
boolean removeAll(Collection<?> c)
4)获取操作
int size() 返回此 collection 中的元素数。
5) boolean retainAll(Collection<?> c) 取两个集合的交集
6) Object[] toArray() 集合变为数组
<T> T[] toArray(T[] a) 另外一种形式
变为数组的时候,数据类型是一致的。
7)Iterator<E> iterator() 迭代器,取出 collection元素的方法
3、练习
需求建立ArrayList的子类对象
注意:CollectionDemo.java使用了未经检查或不安全的操作。
要了解详细信息,请使用—Xlint:unchecked重新编译。
意思是这个程序有安全隐患。这个提示和编译失败没有关系。下面学习了泛型,这个问题就会解决。
再例:Person p=new Person();
ArrayList al=new ArrayList();
Al.add(p);
在内存中怎么存在的呢?Person对象是存储在ArrayList对象中吗?
注意:ArrayList对象是不可能存放对象实体的。它存的是对象的地址值。
1 )Add方法的参数类型是object,以便于接收任意类型的对象。
2) 集合中存储的都是对象的引用,也就是地址。
练习:获取两个集合交集
练习:将集合中元素取出
如果要用循环取出所有元素呢?循环结束条件是什么呢
boolean hasNext() 仍有元素可以迭代,就返回true。
用循环实现:
4、迭代器知识
什么是迭代器呢?其实就是集合的取出元素的方式。是和遍历一样的。
迭代:对于取出,不足以用一个函数来实现,需要多个功能,因此java就将取出的动作封装成一个对象。而且因为数据结构不同,每个取出对象中对取出的动作实现方式都不一样。那么,取出就需要被描述一下,用类来描述,这个类就定义在集合内部。
因为元素就在集合中,要想直接操作元素,定义为内部类最方便。
假如以后再定义一个集合,要对集合中元素取出的时候,还是需要做这一系列动作:
有没有元素?有的话,取出一个元素。判断、取出两个动作。每个容器都是这样,但是怎么判断,怎么取出,依赖于容器中具体的数据结构。取出的动作细节也不一样。但是都有共性内容如判断和取出。那么可以进行共性抽取,形成一个接口,叫做iterator。
那么这些内部类都符合一个规则。该规则就是Iterator。
如何获取集合的取出对象呢?
通过一个对外提供的方法iterator();
就把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素。
那么取出方式就被定义成了内部类。
对于集合中迭代的方法:
A用while循环
Iterator it=al.iterator();//获取迭代器,用于取出集合中的元素
while(it.hasNext())
{ System.out.println(it.next());}
B用for循环
For循环所需变量都定义在for块内,所以for循环结束,变量就会被释放,被认为是比较优化的代码
for(Iterator it=al.iterator();it.hasNext();)
{ System.out.println(it.next());}
要注意的是:迭代器返回的是Object对象,要操作取出的元素,需要转换为元素对应的类型,不过,学习了泛型后,就不用强转了。
三、List集合
Collection
|---List :元素是有序的,元素可以重复,因为该集合体系有索引。
|--Set :元素是无序的。元素不可以重复,没有索引。
1、方法
定义的是ArrayList LinkedList Vector 的共性内容
特有方法:凡是可以操作脚标的方法,都是该体系特有的方法
1) 增加
可以在指定位置插入一个元素
void add(int index, E element)
addALL(index,collection)
2)删除
remove(int index)按照脚标移除
3)修改
E set(int index, E element)
4)查找
get(index);
subList(from,to) 获取一个子集 包含头,不包含尾
listIterator() //list特有的迭代器
可以通过索引获取元素
5)ListIterator listIterator();列表迭代器
A Iterator的做法
这个异常的意思是,当检测到对象的并发修改,但不允许该修改时,就抛出此异常。
分析上例代码:
当运用ArrayList的迭代器方法返回一个迭代器时,可以有两种方法对集合的元素进行操作,一个是ArrayList的方法,一个迭代器的方法。就会产生一个问题
在用迭代器的next方法对集合元素操作的时候,又在使用ArrayList的add方法对元素进行操作,就会产生安全隐患,这叫做并发访问。
怎么解决呢?
要么用集合的方法,要么用迭代器的方法
使用迭代器的方法,我们查阅api文档,有一个方法remove();
It.remove();当遍历到哪个元素,就把取出的元素删除。
但是迭代器,不能添加。它只能做三个动作:判断,取出,删除
没关系,在它子接口ListIterator中,更完善它的操作
B ListIterator
它的方法会比较多有添加,判断,取出,删除,修改等等。
这是List集合特有的迭代器,是iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常。所以,在迭代时,只能用迭代器的方法操作元素,可是Iteratror的方法是有限的,只能对元素进行判断,取出,删除的操作。
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator,该接口只能通过List集合的listIterator方法获取。
ListIterator迭代器的说明:
增删改查,List迭代器都具备,也只有它具备。为什么具备呢?因为List集合内的元素都有脚标。
其他方法
hasNext():是当以正向遍历集合的时候,判断是否后面还有元素.常与next()对应
hasPrevious() :是当以逆向遍历集合的时候,判断前面是否还有元素。常与previous()对应。
2、List集合具体对象的特点
1)List中子类的特点
List
|-----ArrayList
|----LinkedList
|---Vector
这三个子类是因为数据结构不同而被封装成三个子类
List
|-----ArrayList:底层的数据结构使用的是数组结构。
| 特点:查询和修改速度很快,通过脚标。但是添加和删除很慢,因为需要移动元素
|----LinkedList :底层使用的是链表数据结构。
| 特点:查询稍慢。但增删很快。
|---Vector:底层是数组数据结构。和ArrayList功能一样。是1.0版本的,它出现的时候,集合框架还没有诞生。
与ArrayList不同之处就在:Vertor是同步的。ArrayList是不同步的。
所以Vertor增删改查超慢。被ArrayList替代
我们知道集合是可变长度的。
可变长度的数组:
ArrayList默认的长度是10,超过10,它就会new一个新的数组,以15%的延长,把原来数组的元素copy到新数组中。
而Vertor默认长度也是10,而超过10呢,它就100%延长.变成20长度的数组。
2)演示Vector特有方法
凡是有element的方法都是vertor特有的
void addElement(E obj) ;
Enumeration<E> elements() 返回枚举
枚举就是vector的特有取出方式
发现枚举和迭代器很像。
其实,枚举和迭代是一样的,因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。
但是IO的一个方法用到枚举了。因为它是1.0版本的。
三、集合框架LinkedList
1、LinkedList特点:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
2、LinkedList特有方法
A 原来的方法体系
addFirst()
addLast()
顺序的问题
getFirst()
getLast()
获取元素,但不删除元素
removeFirst()
removeLast()
获取元素,但元素被删除
B 新方法体系
添加元素
offerFirst()
offerLast()
获取元素,但不删除元素
peekFirst()
peekLast()
获取元素,同时删除元素
pollFirst()
pollLast()
3、演示
发现是倒序取出的。
查阅api文档,发现,无论是get*方法,还是remove-*方法,都抛出一个异常,叫做没有这个元素。NoSuchElementException
而后期,LinkedList升级,加入一个新的方法
E pollFirst() 相当于removeFirst() 如果列表为空,则返回null
练习
使用LinkedList模拟一个堆栈或者队列数据结构
堆栈:先进后出 first in last out FILO
队列:先进先出 first in first out FifO
------- Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------