集合框架--3
列表List集合的共性方法 列表迭代器ListIterator
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1. List接口
1). Collection常用子接口
(1). Collection常用子接口的继承体系
(2). Collection的子接口:List和Set的区别
[1]. List的特点:元素有序,可重复
[2]. Set的特点:元素无序,不可重复
【List中元素可重复的原因】
List中有索引,索引是不能重复的,但是索引对应的内容是可以重复的。因此,List中的元素可以重复
2). List接口特有的操作方法
【List特有方法的特点】
集合框架的API中,只要操作方法的参数是有关于角标的操作,这个方法就一定是List接口特有的方法。
(1). 增
[1].增加一个:void add(int index, E element);
【特有的add方法返回是void 而不是boolean】
[2]. 增加集合:boolean addAll(int index,Collection<? extends E> c);
(2). 删
删除一个:E remove(int index);
【特有的add方法返回是Object类的对象 而不是boolean】
【没有特有的removeAll方法】
(3). 查/获取
[1]. 获取指定位置的元素
[2]. 获取指定元素的位置
【[1]的逆过程】【String、StringBuffer和StringBuilder都有这个方法】
{1}. 获取元素第一次出现的位置:int indexOf(Objecto);
{2}. 获取元素最后一次出现的位置:intlastIndexOf(Object o);
[3]. 获取指定区间的子集:List<E>subList(int fromIndex, int toIndex);
[4]. 获取与List关联的迭代器对象:Iterator<E>iterator();
[5]. 获取与List关联的列表迭代器对象:Iterator<E>listIterator();
(4). 改
【Collection中没有元素的修改操作】
修改一个:E set(int index, Eelement);
(5). 集合操作
[1]. 获取子集:List<E>subList(int fromIndex, int toIndex);
【List练习】
List al =new ArrayList();
al.add("java001");
al.add("java002");
al.add("java003");
sop(al);
//指定位置添加元素
al.add(1, "java009");
sop(al);
//删除指定位置元素
//al.remove(2);
//sop(al);
//修改指定位置的元素
al.set(2, "java007");
sop(al);
//遍历查询 ----角标查询法
for(int i=0; i< al.size(); i++)
sop("al["+i+"] ="+al.get(i));
//获取元素的位置
sop("index ="+ al.indexOf("java007"));
//取子集合
List subList =al.subList(1, 3);
sop(subList);
打印结果:
2. 列表迭代器ListIterator
1). 问题产生背景
/*需求:对List集合中的元素进行取出,,取出的时候,做一些额外的操作
*迭代的过程中,准备同时添加元素或者删除元素
* */
(1). 代码
/
/出问题的方法
public void methodConcurrentModificarionException(){
Iteratorit = al.iterator();
sop(al);
while(it.hasNext()){
Objectobj =it.next();
if(obj.equals("java002")){
al.add("java008");
}
}
sop(al);
}
运行时,抛出异常:
(2). 异常产生的原因
if(obj.equals("java002")){
al.add("java008");
}
[1]. 原理上 (单线程思想) 的分析:
al存放了元素对象的引用,it也同样存放了对象元素的引用 (通过Iterator it = al.iterator();)。所以,既可以通过al来操作集合,也可以通过it来存取元素。但是在一个线程里面,这样操作可能存在共享数据的安全隐患。
运行到al.add("java008");之前,迭代器引用it仅仅知道容器al原来有6个元素:[java001, java002, java003, java004, java005,java006]。这时候al添加了新的元素(al添加了一个新的元素java008) ,变动了整个集合的底层数据结构,而it还是原有数据的引用集合,并不知道新的元素的存在。
下次迭代循环的时候,it要不要迭代这个新的元素呢?还是按照以前的元素进行迭代?这个时候it本身也不清楚如何处理,此时蹦出了并发访问异常
[2]. 建议的做法
不建议的做法:对同一组数据,使用多个引用进行多种操作。
【建议做法】要么使用集合的操作方式,要么使用迭代器的操作方式
2). 边迭代,边删除
(1). Iterator的删除方法
【发现】Iterator在对数据进行增删改查的处理中,有一个删除的方法:
void remove(); 通过集合关联的Iterator对象本身,可以删除集合中的数据。
【注意】这个方法不接受任何参数
示例代码如下:
//边迭代。边删除
public void methodIterationAndRemove(){
Iteratorit = al.iterator();
sop(al);
while(it.hasNext()){
Objectobj =it.next();
if(obj.equals("java002"))
it.remove();
sop("obj ="+ obj);
}
sop(al);
}
【问题1】这段程序会发生并发异常么?
不会!!因为在迭代元素的时候,是通过it本身的方法remove进行元素的删除的,而不是通过al的remove方法进行删除的。所以,不会发生并发异常。
【问题2】已知:al中的数据有[java001,java002, java003, java004, java005, java006], 当while中的if条件成立的时候,java002这个元素被删除掉。那么进行到sop("obj ="+ obj);的时候,会有打印值么?为什么?
会有打印值,打印出来的仍然是java002。
原因就是:集合中存储的是元素的引用而不是对象元素本身。所以it通过自身的remove方法删除的仅仅是java002这个字符串的引用。但是,在删除之前,语句Object obj=it.next();已经保证java002这个字符串被String类型的引用obj所指向,所以打印的时候,是可以看到java002被打印出来。
运行结果:
【能够边迭代,边添加呢?】iterator类本身没有这样的方法,所以不能通过Iterator这个类来实现。这时候,Java提供了一个叫做ListIterator的Iterator子类来完成这样的操作。
3). ListIterator的使用
(1). ListIterator的概述
[1]. public interfaceListIterator<E> extends Iterator<E>
ListIterator是Iterator接口的子接口。
[2]. Iterator接口的局限性
仅仅有判断【hashNext()】、获取【next()】和删除【remove()】这三个功能。如果想进行其他操作,就要使用Iterator的子接口ListIterator
[3].ListIterator同样具备C、R、U和D
只有List的实例才能获取ListIterator这个类的对象,别的容器实例没有。
(2). 通过ListIterator实现边迭代,边添加
//采用ListIterator进行迭代期间的CRUD
public void methodUsingListIterator(){
ListIterator it = al.listIterator();
sop(al);
while(it.hasNext()){
Object obj =it.next();
if(obj.equals("java002")){
it.add("java008");
}
}
sop(al);
}
运行不会发生异常。
打印结果:
[java001, java002, java003, java004, java005,java006]
[java001, java002, java008, java003, java004,java005, java006]
(3). ListIterator的其他功能
[1]. 与Iterator中hasNext()相对应的方法:hasPrevious()
举例:逆向遍历列表
//双向遍历
public void methodDoubleDirecIteration(){
ListIteratorit = al.listIterator();
sop("正向迭代...");
sop(al);
while(it.hasNext()){
sop(it.next());
}
sop("*************************************");
while(it.hasPrevious()){
sop(it.previous());
}
}
打印结果:
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------