List集合
具体信息请查看 API 帮助文档
实现类:ArrayList、LinkedList、
Vector(现已淘汰)
1. 概述
List是Java中一种常用的数据结构,它是一种有序的集合,可以存储任意类型的对象。
List允许重复的元素,并且可以根据索引位置访问和操作元素。它提供了一系列方法来添加、删除、获取和修改元素,以及其他一些常见的操作,比如查找、排序等。
List是一个接口,Java提供了多个实现List接口的类,常见的有ArrayList和LinkedList。
-
ArrayList是基于数组实现的,它的查询效率较高,但插入和删除元素的效率较低。
-
LinkedList是基于链表实现的,它的插入和删除元素的效率较高,但查询效率较低。
List接口:(因为List是一个接口,因此不能创建List的对象,而要创建它的实现类的对象)
-
有序集合,这里的有序指的是存取顺序
-
用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
-
与Set集合不同,列表通常允许重复的元素
集合的特点:
-
存取有序
-
可以重复
-
有索引
2. 方法
因为List是Collection集合的子类,因此Collection集合中的方法,List集合都可以使用。
2.1 特有方法
特有方法介绍:
方法 | 描述 |
---|---|
void add(int index, E element) | 在指定位置插入指定元素 |
E remove(int index) | 删除指定索引处的元素, 返回被删除元素 |
E set(int index, E element) | 修改指定索引处的元素, 返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
【注意点】
-
void add(int index,E element) 在此集合中的指定位置插入指定的元素
- 细节:集合中的原有元素会依次后移
-
E remove(int index) 删除指定索引处的元素,返回被删除的元素
-
细节:删除元素有两个方法,一是直接通过元素内容删除,二是根据索引删除。
-
如果创建的集合类型是Integer类型的,那删除元素是根据元素内容删除还是根据索引删除?
-
结果是根据索引进行删除的,因为在调用方法的时候,如果方法出现了重载现象,优先调用的是实参跟形参一致的那个方法。
1是int类型的,而根据索引删除的方法里的形参也是int类型,根据内容删除的则是Integer类型,则需要装箱,因此调用的是根据索引进行删除的方法
- 假如非要根据内容进行删除,则需进行手动装箱(此时remove方法是不会自动装箱的),把基本数据类型1,变成Integer类型
-
2.2 代码示例
- 代码示例
package text.text02;
import java.util.ArrayList;
import java.util.List;
/*
List接口:(因为List是一个接口,因此不能创建List的对象,而要创建它的实现类的对象)
有序集合,这里的有序指的是存取顺序
用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
与Set集合不同,列表通常允许重复的元素
集合的特点:
1.存取有序
2.可以重复
3.有索引
*/
public class text27B {
public static void main(String[] args) {
//创建集合对象并添加元素
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
System.out.println("========== 创建集合对象并添加元素 ==========");
System.out.println(list); //[aaa, bbb, ccc, ddd]
System.out.println();
//void add(int index,E element) 在此集合中的指定位置插入指定的元素
//细节:集合中的原有元素会依次后移
System.out.println("========== void add(int index,E element) :在此集合中的指定位置插入指定的元素 ==========");
list.add(3, "eee");
System.out.println(list); //[aaa, bbb, ccc, eee, ddd]
System.out.println();
//E remove(int index) 删除指定索引处的元素,返回被删除的元素
System.out.println("========== E remove(int index) : 删除指定索引处的元素,返回被删除的元素 ==========");
String remove1 = list.remove(3);
System.out.println("删除的元素是:" + remove1); //删除的元素是:eee
System.out.println(list); //[aaa, bbb, ccc, ddd]
System.out.println();
//细节:删除元素有两个方法,一是直接通过元素内容删除,二是根据索引删除。
//如果创建的集合类型是Integer类型的,那删除元素是根据元素内容删除还是根据索引删除?
System.out.println("----- 删除元素的两个方法 -----");
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
Integer remove2 = list1.remove(1);
System.out.println("删除的元素是:" + remove2); //删除的元素是:2
System.out.println("根据索引删除:" + list1); //根据索引删除:[1, 3] 由此可知是根据索引进行删除的,因为在调用方法的时候,如果方法出现了重载现象,优先调用的是实参跟形参一致的那个方法。(1是int类型的,而根据索引删除的方法里的形参也是int类型,根据内容删除的则是Integer类型,则需要装箱,因此调用的是根据索引进行删除的方法)
list1.add(1, 2);
//假如非要根据内容进行删除,则需进行手动装箱(此时remove方法是不会自动装箱的),把基本数据类型1,变成Integer类型
Integer i = Integer.valueOf(1);
boolean remove3 = list1.remove(i);
System.out.println("1是否成功删除:" + remove3); //1是否成功删除:true
System.out.println("根据内容进行删除:" + list1); //根据内容进行删除:[2, 3]
System.out.println();
//E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
System.out.println("========== E set(int index,E element) : 修改指定索引处的元素,返回被修改的元素 ==========");
String set = list.set(1, "sss");
System.out.println("修改的元素是:" + set); //修改的元素是:bbb
System.out.println(list); //[aaa, sss, ccc, ddd]
System.out.println();
//E get(int index) 返回指定索引处的元素
System.out.println("========== E get(int index):返回指定索引处的元素 ==========");
String get = list.get(0);
System.out.println("该索引位置的元素是:" + get); //该索引位置的元素是:aaa
System.out.println(list); //[aaa, sss, ccc, ddd]
}
}
- 输出结果
3. 遍历方式
3.1 迭代器
与共有的 集合遍历方式 一样
3.2 列表迭代器 (特有)
列表迭代器(ListIterator)是Java集合框架中提供的一种专门用于迭代访问List集合的迭代器。
与普通迭代器(Iterator)相比,列表迭代器提供了更多的功能。它不仅可以向前遍历集合,还可以向后遍历集合,还可以在迭代过程中对元素进行添加、修改、删除等操作。
特点 | 常用方法 |
---|---|
双向遍历 | - boolean hasPrevious(): 判断是否有前一个元素 - E previous(): 获取前一个元素 - boolean hasNext(): 判断是否有后一个元素 - E next(): 获取后一个元素 |
修改元素 | - void set(E e): 修改当前所指向的元素 |
添加元素 | - void add(E e): 在当前位置之前添加元素 |
删除元素 | - void remove(): 删除当前所指向的元素 |
元素索引 | - int previousIndex(): 获取前一个元素的索引 - int nextIndex(): 获取后一个元素的索引 |
可选操作 | - int nextIndex(): 获取迭代器的当前索引位置 - void forEachRemaining(Consumer<? super E> action): 对剩余的元素应用给定的操作 |
使用列表迭代器的一般步骤是,首先通过调用listIterator()
方法获取列表迭代器的实例,然后通过调用next()
方法来遍历集合,使用hasNext()
方法来判断是否有下一个元素。
3.3 增强for
与共有的 集合遍历方式 一样
3.4 Lambda表达式
与共有的 集合遍历方式 一样
3.5 普通for循环
List集合有索引,其中原理是利用size()方法、get()方法和循环遍历获得元素
格式:
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(str);
}
3.6 遍历方式的对比
-
迭代器:
-
适用于遍历任何实现了Iterable接口的集合类。
-
提供了hasNext()和next()方法,通过循环调用这两个方法来遍历集合。
-
可以在遍历过程中移除集合中的元素。
-
-
列表迭代器(特有):
-
是迭代器的一种,专门用于遍历List集合。
-
可以双向遍历,通过previous()方法向前遍历,通过next()方法向后遍历。
-
提供了set()方法用于修改当前元素,add()方法用于在当前位置之前添加元素,remove()方法用于删除当前元素。
-
-
增强for循环:
-
适用于遍历数组和实现了Iterable接口的集合类。
-
提供了简洁的语法,不需要手动获取迭代器或使用索引来访问元素。
-
只能进行正向遍历,无法做到修改或删除元素。
-
-
Lambda表达式:
-
适用于遍历实现了Iterable接口的集合类。
-
通过Lambda表达式和函数式接口(如Consumer接口)实现遍历和对元素的操作。
-
可以将遍历和操作的逻辑集中在一起,简化代码。
-
-
普通for循环:
-
可以用于遍历数组和集合类。
-
可以根据需要进行正向或反向遍历。
-
可以通过索引访问元素,且可以根据需要修改或删除元素。
-
3.7 代码示例
- 代码示例
package text.text02;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
/*
List集合的遍历方式:
1. 迭代器
2. 列表迭代器 (特有)
3. 增强for
4. Lambda表达式
5. 普通for循环 (因为List集合有索引,其中原理是利用size()方法、get()方法和循环遍历获得元素)
*/
public class text28A {
public static void main(String[] args) {
//创建集合并添加元素
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
// 1. 迭代器
Iterator<String> it1 = list.iterator();
System.out.print("迭代器遍历:");
while (it1.hasNext()) {
String str1 = it1.next();
//删除元素ccc
if ("ccc".equals(str1)) {
it1.remove();
}
}
System.out.print(list); //迭代器遍历:[aaa, bbb, ddd]
System.out.println();
//2. 列表迭代器 (特有)
ListIterator<String> it2 = list.listIterator();
System.out.print("列表迭代器:");
while (it2.hasNext()) {
String str2 = it2.next();
//添加元素
if ("bbb".equals(str2)) {
it2.add("CCC");
}
}
System.out.print(list); //列表迭代器:[aaa, bbb, CCC, ddd]
System.out.println();
// 3. 增强for
System.out.print("增强for遍历:");
//s是第三方变量,依次表示集合中遍历到的的每一个元素
for (String s : list) {
System.out.print(s + " "); //增强for遍历:aaa bbb CCC ddd
}
System.out.println();
// 4. Lambda表达式
System.out.print("Lambda表达式遍历:");
list.forEach((s) -> System.out.print(s + " ")); //Lambda表达式遍历:aaa bbb CCC ddd
System.out.println();
// 5. 普通for循环
System.out.print("普通for循环遍历:");
for (int i = 0; i < list.size(); i++) {
String str3 = list.get(i);
System.out.print(str3 + " "); //普通for循环遍历:aaa bbb CCC ddd
}
}
}
- 输出结果
4. 注意事项
-
List是一个有序的集合,它允许重复的元素。这意味着可以按照插入顺序访问和操作元素,也可以使用索引来获取和修改元素。但是需要注意,List对于元素的比较是通过equals()方法来判断的,所以确保你的元素类正确实现了equals()方法。
-
当使用ArrayList实现List时,插入和删除元素的效率较低。当需要频繁地在集合的中间位置插入和删除元素时,可以考虑使用LinkedList,它的插入和删除元素的效率较高。
-
在使用List的过程中要注意索引的范围,避免越界访问。List的索引从0开始,到size()-1结束。
-
List集合是可变的,可以动态地增加或删除元素。当需要在集合的任意位置插入或删除元素时,可以使用add()和remove()方法。
-
考虑集合中的元素数量以及对性能的影响。在大量的数据操作中,使用ArrayList的性能通常比LinkedList要好。
-
使用循环遍历或迭代器遍历List集合时要注意避免在循环内部进行集合的增删操作,这可能导致ConcurrentModificationException异常。
-
List集合也支持其他操作,比如查找元素、排序元素等。可以使用contains()方法来判断集合中是否包含某个元素,使用sort()方法对集合进行排序等。