一.List接口
1.概述
继承Collection接口,它是一个元素存取有序的集合
例如,存元素的顺序是11、22、33,那么在集合中,元素的存储就是按照11、22、33的顺序完成
它是一个带有索引的集合,通过索引就可以精确操控集合中的元素,相当于数组索引
与set不同,LIst中可以有重复元素,通过元素的equals方法,来比较是否为重复的元素
LIst接口常用实现类有:
ArrayList集合
LinkedList集合
2.List接口中的抽象方法(特有)
add(int index,object e):向集合指定索引处,添加指定的元素,原元素依次后移
remove(int index):将指定索引中的元素,从集合中删除,返回值为被删除的元素
set(int index,E element):将指定索引处的元素,替换成指定的元素,返回值为替换前的元素
get(int index):获取指定索引处的元素,并返回该元素
3.List遍历
List<Person> a=new LinkedList<>();
a.add(new Person("zs",10));
a.add(new Person("lisi",20));
a.add(new Person("wangwu",30));
Iterator<Person> listItr=a.iterator();
//利用迭代器对象遍历
while(listItr.hasNext()){
System.out.println(listItr.next());
}
//LIst独有的遍历方式
for(int i=0;i<a.size;i++){
System.out.println(a.get(i));
}
二.ListIterator接口
1.概述
List不仅有自己独特的迭代方式,还有自己的迭代器ListIterator
2.ListIterator接口的抽象方法
add(E,e):将指定元素插入列表
boolean hasPrevious():逆向遍历列表,若列表迭代器有多个元素,则返回true,也就是判断是否有前一个元素
previous():返回列表的前一个元素
3.List逆向遍历:
Iterator<Person> itertor=a.iterator();
ListIterator<Person>ListItr=a.listIterator(a.size());
while(ListItr.hasNext()){
System.out.println(ListItr.next());
}
//逆向遍历
//先previous向前移动一个位置,再访问cursor指向的元素
while(listItr.hasPrevious()) {
System.out.println(listItr.previous());
}
三.迭代器的并发修改异常
java.util.ConcurrentModificationException
就是在遍历过程中,使用集合方法修改集合长度
2.出现场景:
首先,在遍历集合的过程中修改集合;其次修改集合行为不是迭代器对象来完成的,而是直接修改Collection对象。
List<String> list=new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
Iterator<String> it=list.iterator();
while(it.hasNext()){
String s=it.next();}
if(s.equals("abc3"){
list.add("ABC3");
}
System.out.println(s);
}
3.原因:
在迭代过程中,使用集合方法对元素进行操作。导致迭代器不知道集合中的变化,容易引发数据的不确定性。迭代器对象,是依赖于当前数据集合产生的,他们应该对应
List<Person> a=new LinkedList<>();
//迭代器
ListIterator<Person>ListItr=a.listIterator();
a.add(new Person("zs",10));
a.add(new Person("lisi",20));
a.add(new Person("wangwu",30));
while(ListItr.hasNext()){
Person p=ListItr.next();
//这种添加元素的方式,会产生异常
//a.add(new Person("zhaoliu",40));
//解决方法:利用迭代器对象添加元素
ListItr.add(new Person("zhaoliu",40));
}
System.out.println(a);
//针对List还有一种,在遍历集合的同时修改集合的解决方案
for(int i=0;i<a.size();i++){
if("lisi".equals(a.get(i).name)){
a.add(new Person("zhaoliu",40));
}
}
System.out.println(a);
四.ArrayList,LinkedList集合
1.ArrayList集合
底层采用的是数组结构,线程不安全,查询快,增删慢
//创建了一个长度为0的Object类型数组
ArrayList al=new ArrayList();
al.add("abc");
//本质:
//底层会创建一个长度为10的Object数组 Object[] obj=new Object[10]
//obj[0]="abc"
//如果添加的元素的超过10个,底层会开辟一个1.5*10的长度的新数组
//把原数组中的元素拷贝到新数组,再把最后一个元素添加到新数组中
2.LinkedList集合
底层采用链表结构,线程不安全,查询慢,增删快
每次查询都要从链头或链尾找起,查询慢,但是删除直接修改元素记录的地址值即可,不需要大量移动元素
LinkedList的索引决定是从链头查找还是链尾查找
- 如果该元素小于元素长度一半,从链头开始找起,如果大于元素长度的一半,则从链尾找起
- LinkedList 提供了大量的操作开始和结尾的方法
- 子类的特有功能:不能多态调用:
addFirst(E) 添加到链表的开头
addLast(E) 添加到链表的结尾
E getFirst() 获取链表的开头
E getLast() 获取链表的结尾
E removeFirst() 移除并返回链表的开头
E removeLast() 移除并返回链表的结尾
3.Vector集合
- Vector 集合数据存储的结构是 数组 结构,为JDK中最早提供的集合,它是线程同步的,线程安全的
- Vector 集合已被 ArrayList 替代