List
1. 概述 & 特点
1.1 概述
- 有序集合(序列),用户可以精确控制列表中每个元素的插入位置
- 用户可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
1.2 特点
- 有索引
- 可以存储重复元素
- 元素存储有序
2. 特有方法
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
2.1 add() & remove()
public class Demo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("hello");
list.add("world");
list.add("world");
System.out.println(list);
//调用void add(int index,E element) 在指定位置插入指定元素
list.add(1,"hahah"); //索引是从0开始的
System.out.println(list);
//调用E remove(int index) 删除指定索引处的元素,返回被删除的元素
System.out.println(list.remove(1));
System.out.println(list);
}
}
/* 输出结果
[hello, world, world]
[hello, hahah, world, world]
hahah
[hello, world, world] */
2.2 set() & get()
public class Demo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("world");
System.out.println(list); //[hello, world, world]
//调用E set(int index,E element)方法 修改指定位置的元素,返回被修改的元素
System.out.println(list.set(1,"hahaha")); //world
System.out.println(list); //[hello, hahaha, world]
//调用E get(int index)方法,返回指定位置的元素
System.out.println(list.get(1)); //hahaha
}
}
/* 输出结果
[hello, world, world]
world
[hello, hahaha, world]
hahaha */
2.3 案例
2.3.1 List集合存储学生对象并遍历
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//List集合存储学生对象并遍历
/*
1. 定义学生类
2. 创建list集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合
遍历方法1. 迭代器方式
for 循环方法
*/
public class Test01 {
public static void main(String[] args) {
//创建list集合对象
List<Student> list = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("哈哈哈", 12);
Student s2 = new Student("嘻嘻嘻", 13);
Student s3 = new Student("吼吼吼", 14);
//将学生对象添加到集合
list.add(s1);
list.add(s2);
list.add(s3);
//遍历集合 1.使用迭代器方式 在Collection中学到迭代器
Iterator<Student> iterator = list.iterator();
while (iterator.hasNext()){
Student s = iterator.next();
System.out.println(s.getName() + "," + s.getAge());
}
System.out.println("================");
//遍历集合 2.使用for循环 + get()方法
for (int i = 0; i < list.size(); i++) {
//利用get()方法返回指定索引处元素
Student s = list.get(i);
System.out.println(s.getName() + "," + s.getAge());
}
}
}
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
4. 并发修改异常
4.1 异常原因
4.1.1 说明
- 迭代器遍历的过程中,通过集合对象修改了集合中的元素,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
- 预期修改值:expectedModCount
- 实际修改值:modCount
4.1.2 代码示例
public class Demo03 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
Iterator<String> iterator = list.iterator();
//进行以下操作或出现 并发修改异常 ConcurrentModificationException
while (iterator.hasNext()){
String s = iterator.next();
if(s.equals("world")){
list.add("java");
}
}
System.out.println(list);
}
}
4.2 解决方法
4.2.1 说明
- 利用for循环遍历,然后用集合对象做对应操作
4.2.2 代码示例
import java.util.ArrayList;
import java.util.List;
public class Demo03 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if (s.equals("hello")){
//注意,如果添加的元素与判断元素相同 ,会导致死循环
list.add(i+1,"hahaha"); // 这里i+1 表示在 hello 后面添加元素
}
}
System.out.println(list);
}
}
5. ListIterator<列表迭代器>
5.1 介绍
-
通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
-
用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
5.2 常用方法
方法名 | 说明 |
---|---|
E next() | 返回迭代中的下一个元素 |
boolean hasNext() | 如果迭代具有更多元素,则返回 true |
E previous() | 返回列表中的上一个元素 |
boolean hasPrevious() | 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 true |
void add(E e) | 将指定的元素插入列表 |
5.2.1 代码示例
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Demo04 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
ListIterator<String> lit = list.listIterator();
//正向遍历 比较少使用列表迭代器 一般使用iterator
while (lit.hasNext()){
String s = lit.next();
System.out.println(s);
}
System.out.println("==============");
//逆向遍历 少用
while (lit.hasPrevious()){
String s = lit.previous();
System.out.println(s);
}
while (lit.hasNext()){
String s = lit.next();
if (s.equals("hello")){
//区别与迭代器,列表迭代器在进行此操作时不会发生并发修改异常
lit.add("haha");//这个时候箭头应该位于hello下方,所以是在hello后插入指定元素
}
}
System.out.println(list);
}
}
/* 输出结果
hello
world
==============
world
hello
[hello, haha, world] */
5.2.2 注意点
-
正向遍历 hasNext() & next()
- 第一次循环,箭头位于"hello"上方,所以next()返回迭代中的下一个元素,就会返回"hello",箭头移至"world"上方
- 第二次循环,箭头位于"world"上方,所以调用方法输出的是"world",箭头移至world下方
- hasNext()方法判断没有元素,返回false,结束while循环
- 一般会直接使用迭代器进行遍历,较少使用列表迭代器
-
反向遍历 hasPrevious() & previous()
- 流程与正向遍历相同,但是最初箭头是在"hello"的上方,所以如果直接进行反向遍历,hasPrevious()会返回false,导致控制台没有输出结果
- 这种方法用的少,所以理解就可以
6. 遍历集合的三种方法<总结>
6.1 说明
-
使用 迭代器方法 遍历结合
-
使用 for循环 + get() 方法 遍历集合
-
使用增强For循环遍历集合
-
//增强For循环 for(元素数据类型 变量名 : 数组/集合对象名){ 循环体 }
-
6.2 代码示例
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class AddDemo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
System.out.println(list);
//迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("=================");
//for + get()
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
System.out.println("================");
//增强for循环
for (String s : list) {
System.out.println(s);
}
}
}
7. 数据结构
7.1 栈 &队列
- 栈:先进后出
- 队列:先进先出
7.2 数组 & 链表
- 数组:查询快,增删慢
- 链表:查询慢,增删快
8. List集合的实现类<子类>
8.1 子类
名称 | 说明 |
---|---|
ArrayList集合 | 底层数据结构是数组,查询快,增删慢 |
LinkedList集合 | 底层数据结构是链表,查询慢,增删快 |
8.1.1 ArrayList集合
//创建ArrayList集合对象
ArrayList<String> array = new ArrayList<String>();
8.1.2 LinkedList集合
8.1.2.1 特有方法
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
8.1.2.2 代码示例
import java.util.ArrayList;
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
//创建集合对象
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("hello");
linkedList.add("world");
System.out.println(linkedList);
System.out.println("============:");
//public void addFirst(E e) 在该列表开头插入指定的元素
linkedList.addFirst("1java1");
System.out.println(linkedList);
System.out.println("============");
//public void addLast(E e) 将指定的元素追加到此列表的末尾
linkedList.addLast("2java2");
System.out.println(linkedList);
System.out.println("============");
//public E getFirst() 返回此列表中的第一个元素
System.out.println(linkedList.getFirst());
System.out.println("============");
//public E getLast() 返回此列表中的最后一个元素
System.out.println(linkedList.getLast());
System.out.println("============");
//public E removeFirst() 从此列表中删除并返回第一个元素
System.out.println(linkedList.removeFirst());
System.out.println(linkedList);
System.out.println("============");
//public E removeLast() 从此列表中删除并返回最后一个元素
System.out.println(linkedList.removeLast());
System.out.println(linkedList);
}
}
//输出结果
[hello, world] //最初集合的元素
============
[1java1, hello, world] //调用addFirst(E e)方法
============
[1java1, hello, world, 2java2] //调用addLast(E e)方法
============
1java1 //调用getFirst()方法
============
2java2 //调用getLast()方法
============
1java1 //调用removeFirst()方法
[hello, world, 2java2]
============
2java2 //调用removeLast()方法
[hello, world]