注意:该文章有List接口的常见子类ArrayList和LinkedList详解 —— Java系列学习笔记 --- 集合(4) 集合框架知识汇总
一、List集合概述
List集合代表元素有序并且可以重复的集合,这是因为List集合默认按照元素的添加顺序为每个元素添加对应的索引。List集合和数组一样,是通过索引去访问对象的,所以能够允许使用重复元素。
1.1 List接口
List作为Collection接口的子接口,继承了Collection接口里的全部方法,除此之外,List集合还增加了一些额外的方法:
- Object get(int index):获取指定索引处的元素。
- void add(int index,ObjeCt Elemt):将元素Elemt插入到指定位置。
- boolean addAll(int index,Collection c):将集合c里面的所有元素都插入List集合中的指定位置。
- Object remove(int index):删除并返回指定索引处的元素。
- Object set(int index,Object Elemt):替换并返回指定索引处的元素。
- int indexOf(Object obj):返回指定对象在List集合中第一次出现的位置索引。
- int lastIndexOf(Object obj):返回指定对象在List集合中最后一次出现的位置索引。
- List subList(int fromIndex,int toIndex):返回从索引fromIndex到所有toIndex处的所有集合元素组成的子集合。
- void replaceAll(UnaryOperator operator):根据operator自定规则重新设置List集合的所有元素。
- void sort(Comparator c):根据参数规则对List集合元素进行排序。
例如下面的程序示范了List集合的常规用法
List ls = new ArrayList();
for(int i=0;i<5;i++){
ls.add(i,i+1);
}
System.out.println(ls);
ls.add(3,8);
System.out.println(ls);
ls.set(2,6);
ls.add(5,6);
System.out.println(ls);
ls.remove(4);
System.out.println(ls);
System.out.println(ls.indexOf(6));
System.out.println(ls.lastIndexOf(6));
System.out.println(ls.subList(1,3));
//升序排序
ls.sort((a,b)-> (Integer)a-(Integer)b);
System.out.println("升序排序:"+ls);
//降序排序
ls.sort((b,a)-> (Integer)a-(Integer)b);
System.out.println("降序排序:"+ls);
输出结果如下图所示
需要注意的是,上诉的一些操作函数,例如indexOf()方法中的6实际上一个Integer值为6的对象,无论是往List集合添加对象还是想要查询List集合中对象的位置,传递的都是一个新的对象。那么问题来了,为什么两个并不相同的对象依旧可以范围集合中匹配对象的索引呢?其实,List判断两个对象是否相等的标准是通过equals()方法比较返回的结果来判断两个对象是否相等。
public class ListTest1 {
public static void main(String[] args){
List persons = new ArrayList();
persons.add("张三");
persons.add("李四");
persons.add("王五");
System.out.println(persons); //[张三, 李四, 王五]
persons.remove(new A());
System.out.println(persons); //[李四, 王五]
persons.remove(new A());
System.out.println(persons); //[王五]
}
}
class A{
public boolean equals(Object obj){
return true;
}
}
从这个案例,我们可以看到,我们重写了A对象的equals方法总是返回true,所以每次通过该对象去匹配List集合中要删除的对象时,总是返回true。所以每次从List集合中删除A对象时,总是删除List集合中的第一个元素。
另外需要注意的,List中的set(int index,Object obj)方法在替换指定位置中的对象时,指定的索引必须是List集合中的有效索引。例如集合长度为5,就不能指定替换索引为5处的元素,因为此处并没有对象,add()方法同理。
1.2 Listlterator接口
与Set对象只提供了一个iterator()方法不同,List还额外提供了一个listIterator()方法,该方法返回一个ListIterator对象,ListIterator接口继承了Iterator接口,提供了专门操作List的方法。ListIterator接口在Iterator接口基础上增加了如下方法。
- boolean hasPrevious():返回该迭代器关联的集合是否还上一个元素
- Object previous():返回该迭代器的上一个元素
- void add(Object o):在指定位置插入一个元素
与Iterator相比,ListIterator增加了向前迭代的功能(Iterator只能向后迭代),而且ListIterator还可以通过add()方法想List集合中添加元素(Iterator只能删除元素)。下面程序示范了ListIterator的用法。
public class ListIteratorTest {
public static void main(String[] args) {
List persons = new ArrayList();
persons.add("张三");
persons.add("李四");
persons.add("王五");
ListIterator lit = persons.listIterator();
System.out.println("=== 开始正向迭代 ===");
while(lit.hasNext()){
System.out.println(lit.next());
lit.add("- 插入新对象 -");
}
System.out.println("=== 开始反向迭代 ===");
while(lit.hasPrevious()){
System.out.println(lit.previous());
}
}
}
最终的输出结果如下图所示:
=== 开始正向迭代 ===
张三
李四
王五
=== 开始反向迭代 ===
- 插入新对象 -
王五
- 插入新对象 -
李四
- 插入新对象 -
张三