List
List集合概述和特点
List集合概述
- 有序集合(也称为序列),用户可以精准控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
List集合特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//List集合特点
// 有序:存储和取出的元素顺序一致
// 可重复:存储的元素可以重复
public class ListDemo {
public static void main(String[] args) {
// 创建集合对象
List<String> list = new ArrayList<String>();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
list.add("world");
// //输出集合对象
// System.out.println(list);
// 采用迭代器的方式遍历
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
运行结果:
List集合特有方法
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引出的元素 |
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//List集合特点
// 有序:存储和取出的元素顺序一致
// 可重复:存储的元素可以重复
//List集合特有方法
//void add(int index,E element) 在此集合中的指定位置插入指定的元素
//E remove(int index)删除指定索引处的元素,返回被删除的元素
//E set(int index,E element)修改指定索引处的元素,返回被修改的元素
//E get(int index)返回指定索引出的元素
public class ListDemo {
public static void main(String[] args) {
// 创建集合对象
List<String> list = new ArrayList<String>();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
// void add(int index,E element) 在此集合中的指定位置插入指定的元素
list.add(1,"javaee");//运行结果:[hello, world, java]
list.add(11,"javaee");//运行结果:IndexOutOfBoundsException
// E remove(int index)删除指定索引处的元素,返回被删除的元素
System.out.println(list.remove(1));
/*运行结果:
world
[hello, java]*/
System.out.println(list.remove(11));//运行结果:IndexOutOfBoundsException
// E set(int index,E element)修改指定索引处的元素,返回被修改的元素
System.out.println(list.set(1, "javaee"));
/*运行结果:
world
[hello, javaee, java]*/
System.out.println(list.set(11, "javaee"));//IndexOutOfBoundsException
// E get(int index)返回指定索引出的元素
System.out.println(list.get(1));
/*运行结果:
world
[hello, world, java]*/
System.out.println(list.get(11));//IndexOutOfBoundsException
// //输出集合对象
System.out.println(list);
// 用get()方法遍历集合
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
/*运行结果:
hello
world
java */
}
}
案例:List集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
//定义学生类
public class Student {
private String name;
private int 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;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
public class ListDemo2 {
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("小红", 11);
// 把学生添加到集合
list.add(s1);
list.add(s2);
list.add(s3);
// 遍历集合(迭代器方法)
Iterator<Student> it = list.iterator();
while (it.hasNext()) {
Student s = it.next();
System.out.println(s.getName() + "," + s.getAge());
}
System.out.println("----------------");
// 遍历集合(for循环方法)
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(s.getName() + "," + s.getAge());
}
/*运行结果:
小白,12
小黑,13
小红,11
----------------
小白,12
小黑,13
小红,11*/
}
}
并发修改异常
并发修改异常:
- ConcurrentModificationException
产生原因:
- 迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案:
- 用for循环遍历,然后用集合对象做对应的操作即可
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*需求: 有一个List集合 里面有三个元素 hello world java 遍历集合,得到每一个元素,看有没有world,如果有,就添加一个javaee
ConcurrentModificationException:当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常
实际修改集合的次数不等于预期修改集合的次数
*/
public class ListDemo3 {
public static void main(String[] args) {
// 创建集合对象
List<String> list = new ArrayList<String>();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
//遍历集合,得到每一个元素,看有没有world,如果有,就添加一个javaee
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();//【***】
System.out.println(s);
if (s.equals("world")) {
list.add("javaee");
}
}
/*运行结果:
ConcurrentModificationException
【***】通过迭代器获取元素时,每次都要判断它的预期修改值和实际修改值是否相同
*/
//用for循环遍历
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
if (s.equals("world")) {
list.add("javaee");
}
}
/*运行结果:
[hello, world, java, javaee]*/
//输出集合对象
System.out.println(list);
}
}
ListIterator
ListIterator:列表迭代器
- 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获得列表中迭代器的当前位置
ListIterator中的常用方法
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回true
- E previous():返回列表中的上一个元素
- boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
- void add(E e):将指定的元素插入列表
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/*
ListIterator:列表迭代器
通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获得列表中迭代器的当前位置
ListIterator中的常用方法
E next():返回迭代中的下一个元素
boolean hasNext():如果迭代具有更多元素,则返回true
E previous():返回列表中的上一个元素
boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
void add(E e):将指定的元素插入列表
*/
public class ListIteratorDemo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
//通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
ListIterator<String> lit = list.listIterator();
//正向遍历
while (lit.hasNext()) {
String s = lit.next();
System.out.println(s);
}
System.out.println("-----------");
//E previous():返回列表中的上一个元素
//boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
//逆向遍历
while (lit.hasPrevious()) {
String s = lit.previous();
System.out.println(s);
}
/*运行结果:
hello
world
java
-----------
java
world
hello
*/
//void add(E e):将指定的元素插入列表
//获取列表迭代器
ListIterator<String> lit1 = list.listIterator();
while (lit1.hasNext()) {
String s = lit1.next();
if (s.equals("world")) {
lit1.add("javaee");
//Itetator里无法实现添加,但是ListIterator可以实现
/*public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;-----此时这两个值是一致的,因此不会出现并发修改异常
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}*/
}
}
/*运行结果:
[hello, world, javaee, java]*/
System.out.println(list);
}
}
增强for循环
增强for的目的:简化数组和Collection集合的遍历
- 实现Iterator接口的类允许其对象成为增强型for语句的目标
- 它是JDK5之后出现的,其内部原理是一个Iterator迭代器
增强for的格式
- 格式:
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}
- 范例:
int[] arr={1,2,3,4,5};
for(int i:arr){
System.out.println(i);
}
代码演示:
import java.util.ArrayList;
import java.util.List;
/*增强for的目的:简化数组和Collection集合的遍历
实现Iterator接口的类允许其对象成为增强型for语句的目标
它是JDK5之后出现的,其内部原理是一个Iterator迭代器
增强for的格式
格式:
java
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}*/
public class ForDemo {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
for (int i : arr) {
System.out.println(i);
}
/*运行结果:
1
2
3
4
5*/
System.out.println("--------");
String[] strArray = { "hello", "world", "java" };
for (String s : strArray) {
System.out.println(s);
}
/*运行结果:
hello
world
java*/
System.out.println("--------");
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for (String s : list) {
System.out.println(s);
}
/*运行结果:
aaa
bbb
ccc*/
System.out.println("--------");
//验证:内部原理是一个Iterator迭代器
for (String s : list) {
if (s.equals("bbb")) {
list.add("ddd");
}
}
/*运行结果:
ConcurrentModificationException*/
}
}
运行结果:
案例:List集合存储学生对象用三种方式遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
//定义学生类
public class Student {
private String name;
private int 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;
}
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/*
案例:List集合存储学生对象用三种方式遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
*/
public class ListDemo4 {
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("小红", 11);
// 把学生添加到集合
list.add(s1);
list.add(s2);
list.add(s3);
//遍历集合1:迭代器,集合特有的遍历方式
ListIterator<Student> lit = list.listIterator();
while (lit.hasNext()) {
Student s = lit.next();
System.out.println(s.getName() + "," + s.getAge());
}
System.out.println("--------");
//遍历集合2:普通for,带有索引的遍历方式
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(s.getName() + "," + s.getAge());
}
System.out.println("--------");
//遍历集合3:增强for,最方便的遍历方式
for (Student s : list) {
System.out.println(s.getName() + "," + s.getAge());
}
}
}
运行结果:
数据结构
数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合
通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率
常见数据结构之栈
数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程称为:弹/出栈
例如:进栈时,是从栈底到栈顶,为:ABCD;出栈时,是从栈顶到栈底,为:DCBA
由此可见:栈是一种数据先进后出的模型
常见数据结构之队列
数据从后端进入队列模型的过程称为:入队列
数据从前端离开队列模型的过程称为:出队列
例如:入队时,是按照ABCD的顺序,从队列最后进入队列的;出队时,是按照ABCD的顺序,从队列前面离开队列的
由此可见:队列是一种数据先进先出的模型
常见数据结构之数组
查询数据通过索引定位,查询任意数据耗时相同,查询速度快
删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低
添加数据时,添加位置后的每个数后移,再添加元素,添加效率低
由此可见:数组是一种查询快,增删慢的模型
常见数据结构之链表
链表中的每个元素被称为结点
结点的存储位置被称为地址
地址里面存储有具体的数据以及下一个结点的地址
头结点里面有一个head和空地址(表示结束)
例如:
-
首先,有一个头结点,(head,空地址)
-
要存储一个数据A,保存在地址11位置
则在11位置上有一个(A,空地址),将头结点的空地址改为11,即(head,11)指向(A,空地址) -
要存储一个数据B,保存在地址37位置
则在37位置上有一个(B,空地址),将A结点的空地址改为37,即(head,11)指向(A,37)指向(B,空地址) -
要在数据AB之间添加一个数据C,保存在54位置
则在54位置上有一个(C,空地址),将C结点的空地址改为37,再把A结点的地址值改为54,即(head,11)指向(A,54)指向(C,37)指向(B,空地址) -
要删除数据A
则把头结点的地址改为54,再删除数据A,即head,54)指向(C,37)指向(B,空地址) -
查询数据B是否存在
则要从头head开始查询
由此可见:链表是一种增删快,查询慢的模型(对比数组)
List集合子类特点
List集合常用子类:ArrayList,LinkedList
- ArrayList:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询慢,增删快
练习:
分别使用ArrayList和LinkedList完成存储字符串并遍历
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;
/*
List集合常用子类:ArrayList,LinkedList
ArrayList:底层数据结构是数组,查询快,增删慢
LinkedList:底层数据结构是链表,查询慢,增删快
练习:
分别使用ArrayList和LinkedList完成存储字符串并遍历
*/
public class ListDemo5 {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<String> alist = new ArrayList<String>();
alist.add("hello");
alist.add("world");
alist.add("java");
System.out.println("----ArrayList----");
//遍历1
for (String s : alist) {
System.out.println(s);
}
System.out.println("--------");
//遍历2
for (int i = 0; i < alist.size(); i++) {
String s = alist.get(i);
System.out.println(s);
}
System.out.println("--------");
//遍历3
ListIterator<String> lit = alist.listIterator();
while (lit.hasNext()) {
String s = lit.next();
System.out.println(s);
}
System.out.println("----LinkedList----");
//创建LinkedList集合对象
LinkedList<String> llist = new LinkedList<String>();
llist.add("hello");
llist.add("world");
llist.add("java");
//遍历1
for (String s : llist) {
System.out.println(s);
}
System.out.println("--------");
//遍历2
for (int i = 0; i < llist.size(); i++) {
String s = llist.get(i);
System.out.println(s);
}
System.out.println("--------");
//遍历3
ListIterator<String> lit2 = llist.listIterator();
while (lit2.hasNext()) {
String s = lit2.next();
System.out.println(s);
}
}
}
运行结果:
LinkedList集合的特有功能
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
import java.util.LinkedList;
/*
LinkedList集合的特有功能
public void addFirst(E e) 在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素
public E removeLast()从此列表中删除并返回最后一个元素
*/
public class LinkedListDemo {
public static void main(String[] args) {
//创建集合对象
LinkedList<String> llist = new LinkedList<String>();
llist.add("hello");
llist.add("world");
llist.add("java");
// public void addFirst(E e) 在该列表开头插入指定的元素
// public void addLast(E e)将指定的元素追加到此列表的末尾
llist.addFirst("javase");
llist.addLast("javaee");
/*运行结果:
[javase, hello, world, java, javaee]
*/
// public E getFirst()返回此列表中的第一个元素
// public E getLast()返回此列表中的最后一个元素
System.out.println(llist.getFirst());
System.out.println(llist.getLast());
/*运行结果:
hello
java
[hello, world, java]
*/
// public E removeFirst()从此列表中删除并返回第一个元素
// public E removeLast()从此列表中删除并返回最后一个元素
System.out.println(llist.removeFirst());
System.out.println(llist.removeLast());
/*运行结果:
hello
java
[world]
*/
System.out.println(llist);
}
}