List
是Collection的子接口。特点:有序(存储顺序和取出顺序一致)、可重复。
List的子类特点
ArrayList
:- 底层数据结构是数组,查询快,增删慢。
- 线程不安全,效率高。
Vector
:- 底层数据结构是数组,查询快,增删慢。
- 线程安全,效率低。
LinkedList
:- 底层数据结构是链表,查询慢,增删快。
- 线程不安全,效率高。
List集合的特有功能
- 添加功能
- void
add
(int index, Object element):在指定位置添加元素
- void
- 获取功能
- Object
get
(int index):获取指定位置的元素
- Object
- 列表迭代器
- ListIterator
listIterator()
:List集合特有迭代器
- ListIterator
- 删除功能
- Object
remove
(int index):根据索引删除元素,返回被删除的元素
- Object
- 修改功能
- Object
set
(int index, Object element):根据索引修改元素,返回被修饰的元素
- Object
List相关方法参数是索引值,会根据索引值操作集合。
public class ListDemo {
public static void main(String[] args) {
// 创建集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
// void add(int index,Object element):在指定位置添加元素
list.add(3, "android");//没有问题
// IndexOutOfBoundsException
// list.add(4, "javaee"); //有问题
System.out.println("list:" + list);
// Object get(int index):获取指定位置的元素
System.out.println("get:" + list.get(1));
// IndexOutOfBoundsException
// System.out.println("get:" + list.get(11));
// Object remove(int index):根据索引删除元素,返回被删除的元素
System.out.println("remove:" + list.remove(1));
// IndexOutOfBoundsException
// System.out.println("remove:" + list.remove(11));
System.out.println("list:" + list);
// Object set(int index,Object element):根据索引修改元素,返回被修饰的元素
System.out.println("set:" + list.set(1, "javaee"));
System.out.println("list:" + list);
}
}
输出:
list:[hello, world, java, android]
get:world
remove:world
list:[hello, java, android]
set:java
list:[hello, javaee, android]
因为List是有序的,所以List特有功能均与下标相关,可以通过下标获取、增加、修改、删除下标对应的元素值。
List特有遍历
1、size()和get()方法结合使用
public class ListDemo {
public static void main(String[] args) {
// 创建集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
for (int x = 0; x < list.size(); x++) {
String s = (String) list.get(x);
System.out.println(s);
}
}
}
2、列表迭代器
ListIterator
listIterator():List集合特有的迭代器,继承了 Iterator 迭代器,所以,就可以直接使用hasNext()
和next()
方法。
- 特有功能:
- Object
previous()
:获取上一个元素 - boolean
hasPrevious()
:判断是否有元素 - void
remove()
: 删除当前元素 - void
set(E e)
:设置当前元素 - void
add(E e)
:在当前元素后添加元素
- Object
public class ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List list = new ArrayList();
list.add("hello");
list.add("world");
list.add("java");
// ListIterator listIterator()
ListIterator lit = list.listIterator(); // 子类对象
while (lit.hasNext()) {
String s = (String) lit.next();
System.out.println(s);
if ("world".equals(s)) {
lit.set("123");
lit.add("456");
}
}
System.out.println(list);
while (lit.hasPrevious()) {
String s = (String) lit.previous();
System.out.println(s);
}
System.out.println("-----------------");
// 迭代器
Iterator it = list.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
System.out.println("-----------------");
}
}
输出:
hello
world
java
[hello, 123, 456, java]
java
456
123
hello
-----------------
hello
123
456
java
-----------------
注意:ListIterator 可以通过 previous() 实现逆向遍历,但是必须先正向遍历,才能逆向遍历,所以一般无意义,不使用。
需求:有一个集合,判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
public class ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
// 迭代器遍历
Iterator it = list.iterator();
while (it.hasNext()) {
String s = (String) it.next();
if ("world".equals(s)) {
list.add("javaee");
}
}
System.out.println("list:" + list);
}
}
上述代码运行报错:ConcurrentModificationException。因为迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
解决思路:
- 迭代器迭代元素,迭代器修改元素。
- 集合遍历元素,集合修改元素。
1、迭代器迭代元素,迭代器修改元素
public class ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
// 方式1:迭代器迭代元素,迭代器修改元素
// 而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
String s = (String) lit.next();
if ("world".equals(s)) {
lit.add("javaee");
}
}
System.out.println("list:" + list);
}
}
输出:
list:[hello, world, javaee, java]
2、集合遍历元素,集合修改元素
public class ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
// 方式2:集合遍历元素,集合修改元素(普通for)
for (int i = 0; i < list.size(); i++){
String s = (String) list.get(i);
if(s.equals("world")){
list.add("javaee");
}
}
System.out.println("list:" + list);
}
}
输出:
list:[hello, world, java, javaee]
观察结果发现,迭代器更新元素是跟在刚才迭代的元素后面的。而集合遍历元素,元素在集合的最后添加的。
如果使用增强for呢?代码如下:
public class ListDemo {
public static void main(String[] args) {
// 创建List集合对象
List list = new ArrayList();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
// 增强for
for (Object obj : list){
String s = (String) obj;
if(s.equals("world")){
list.add("javaee");
}
}
System.out.println("list:" + list);
}
}
和原先一样报错:ConcurrentModificationException。因为增强for编译器默认使用迭代器替换,最终,还是迭代器遍历,集合修改。