文章目录
集合简介
集合概述
集合引入原因:
编程的时候如果要存储多个数据,使用长度固定的数组存储格式,不一定可以满足需求。
xhj理解:也就是数组存储格式是长度固定的,
动态初始化int[] arr = new int[x] ;
静态初始化int[] arr = {x,x,x};
集合类的特点:
提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变;
Java中集合按照存储结构分为单列集合Collection和双列集合Map;
集合的体系结构:
理解xhj:
学习接口的原因是:当学了Collection接口后,再学习List接口,只需要学习List接口特有的内容即可;
学习实现类的原因是:接口不能直接创建对象并调用方法,而接口的实现类可以直接创建对象并实现方法调用;
List集合子类的特点
ArrayList、LinkedList、Vector
概述:
- List集合常用子类:ArrayList、LinkedList
- ArrayList集合实现List接口,是List接口的可调整大小的数组实现,特点:查询快,增删慢;
- LinkedList集合实现List接口,底层是双链表实现List接口,特点:查询慢、增删快;
案例:使用ArrayList和LinkedList实现字符串的存储和遍历
分析:
因为List有三种遍历方式:
1 使用迭代器 iterator
List<E> list = new ArrayList<E>(); 创建List集合对象
Iterator<E> it = list.iterator(); 获取迭代器对象
while(it.hasNext()){ 判断是否有可迭代的对象
E e = it.next(); 获取迭代器中的元素
}
2 使用简单for循环
List<E> list = new ArrayList<E>(); 创建list集合对象
for(int i = 0 ; i < list.size() ; i++){ 遍历集合中元素
E e = list.get(i); get方法获取集合元素
}
3 增强for循环获取元素
List<E> list = new ArrayList<E>(); 创建list集合对象
for(String str : list){
//for循环括号里是 集合中元素类型 变量名:集合对象
}
案例完整代码:
//29-ListDemo
public class ListDemo {
public static void main(String[] args) {
// ArrayList集合
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("java");
array.add("world");
//遍历
Iterator<String> it = array.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
System.out.println("---------------");
for(int i = 0;i<array.size();i++){
String s = array.get(i);
System.out.println(s);
}
System.out.println("---------------");
// LinkedList集合
LinkedList<String> linkL = new LinkedList<String>();
linkL.add("go do it");
linkL.add("just do it");
for (String s : linkL){
System.out.println(s);
}
}
}
案例:ArrayList集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储三个学生对象,使用程序实现在控制台遍历该集合
// 215-test1-ArrayListDemo
public class ArrayListDemo {
public static void main(String[] args) {
ArrayList<Student> array = new ArrayList<Student>();
Student s1 = new Student("汪苏泷",33);
Student s2 = new Student("许嵩", 36);
Student s3 = new Student("徐良", 34);
array.add(s1);
array.add(s2);
array.add(s3);
// 迭代器遍历
Iterator<Student> it = array.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName() + ", " + s.getAge());
}
System.out.println("------------");
// 简单for循环遍历
for (int i = 0;i<array.size(); i++){
Student s = array.get(i);
System.out.println(s.getName() + ", " + s.getAge());
}
System.out.println("-------------");
// 增强for循环遍历
for(Student stu:array){
System.out.println(stu.getName() + ", " + stu.getAge());
}
}
}
List集合
概述
- interface List< E >表示它是一个接口,并且参数是泛型
- 软件包是java.util 表示使用时需要导包
- List是个接口,不能直接实例化,需要借助它的实现类进行实例化;
- 有序集合(又称为序列),用户可以精确控制列表中每个元素的插入位置,也可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
- List继承自Collection,则可以采用迭代器进行元素遍历
- List集合是有序的,它是按照元素的添加顺序来存储对象。
特点
有序:存储和取出的元素顺序一致;
可重复:存储的元素可以重复。
案例:
//29-test3
public class ListDemo1 {
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);
//[hello, world, java] 输出
// 说明list列表中 元素的存储和取出顺序相同
//使用迭代器遍历元素
Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
List集合常用方法
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
理解xhj:
1 List集合常用方法中,带有index索引的,都不可以越界;且常用方法都带有index索引;
2 List集合遍历集合的形式 目前阶段有两种:
方法一:
Collection<E> c = new ArrayList<E>(); // 集合对象
E e = c.iterator(); // 使用迭代器获取集合对象的元素
while(e.hasNext()){ // 用于判断是否可以迭代多个元素
e.next(); // 获取对象的元素
}
方法二:
List<E> list = new ArrayList<E>(); //获取List对象
//遍历对象
for(int i= 0;i < list.size();i++){ //size()方法是Collection的
list.get(i); //获取集合元素
}
案例:List集合存储学生对象并遍历
// 29-test2
//List集合存储学生对象并遍历
public class ListDemo {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
Student s1 = new Student("汪苏泷",33);
Student s2 = new Student("许嵩",33);
Student s3 = new Student("郁可唯",33);
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());
}
}
}
ArrayList
概述
ArrayList<E>
-
说明:
①可调整大小的数组实现。
②< E>:是一种特殊的数据类型,泛型。
xhj理解:也就是集合中存储元素的数据类型 -
在出现E的地方使用引用数据类型替换。
例如:ArrayList< String >; ArrayList< Student >
扩展
2022/5/31 |
---|
ArrayList元素可以是数组 |
构造方法和添加方法
方法名 | 说明 |
---|---|
public ArrayList() | 创建一个空的集合对象 |
public ArrayList(int initialCapacity) | 构造具有指定初始容量的空列表 |
public ArrayList(Collection < ? extends E > c) | 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序创建 |
public boolean add(E e) | 将指定的元素追加到指定集合的末尾,返回true或false表示操作成功/操作失败 |
public void add(int index,E element) | 在此集合中的指定位置插入指定元素 |
案例:
//117--ArrayListDemo1
//ArrayList构造方法和添加对象
public class ArrayListDemo1 {
public static void main(String[] args){
//创建ArrayList对象——public ArrayList()构造方法
// ArrayList<String> array = new ArrayList<>(); //两种方式都可以
ArrayList<String> array = new ArrayList<String>();
** jdk7之后的新特性,new ArrayList<> 尖括号的内容会根据前面的ArrayList<String>进行推断的。
** ArrayList添加方法——public boolean add(E e)
// System.out.println(array.add("hello"));//输出true 主要用于判断添加是否成功,一般不进行输出。
array.add("hello");
array.add("java");
array.add("world");
//结果输出:array:[hello, java, world] 会自动在每个元素之间添加逗号
** Arraylist添加方法——public void add(int index,E element)
// array.add(1, "lxm");
// array:[hello, lxm, java, world]
**在ArrayList对象末尾之后再添加元素,末尾索引是2 所以要在末尾添加则索引应该是3
// array.add(3,"lxm");
// array:[hello, java, world, lxm]
**在ArrayList对象末尾之后隔几个元素添加元素,末尾索引是2,添加位置是4
// array.add(4,"lxm");
**报错:IndexOutOfBoundsException
**总结 也就是说 public void add(int index,E element)方法index的范围是0-集合长度
System.out.println("array:" + array);
}
}
xhj理解:
public void add(int index,E element)方法index的范围是0-集合长度;
例如集合长度是3,则index索引值就是0,1,2,3
ArrayList集合常用方法
方法名 | 说明 | 举例 |
---|---|---|
public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 | 集合.remove(Element e) |
public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 | 集合.remove(index) |
public E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 | 集合.set(index,Element) |
public E get(int index) | 返回指定所引处的元素 | 集合.get(index) |
public int size() | 返回集合中的元素的个数 | 集合.size() |
案例:
// 117--ArrayListDemo2
//ArrayList常用方法
public class ArrayListDemo2 {
public static void main(String[] args){
//创建集合对象 ArrayList
ArrayList<String> array = new ArrayList<String>();
//使用public boolean add(String s)方法,返回
array.add("hello");
array.add("java");
array.add("world");
**public boolean remove(Object o)——删除指定元素
System.out.println(array.remove("hello"));
//输出:true array:[java, world]
System.out.println(array.remove("javaee"));
//输出:false array:[hello, java, world]
删除的元素在ArrayList对象中没有,所以array.remove没有执行,返回值是false
**public E remove(int index)根据索引删除对应的值,返回被删除的元素
System.out.println(array.remove(1));
//输出java array:[hello, world]
System.out.println(array.remove(3));
报错:IndexOutOfBoundsException 因为元素一共有3个 索引值应该最大是2
**public E set(int index,E element)——根据索引修改指定元素,并返回被修改的元素
System.out.println(array.set(1, "javaee"));
//输出:java array:[hello, javaee, world]
System.out.println(array.set(3, "javaee"));
//报错:IndexOutOfBoundsException
**public E get(int index)——返回指定索引处的元素
System.out.println(array.get(0));
System.out.println(array.get(1));
System.out.println(array.get(2));
//输出:hello,java,world,array:[hello, java, world]
// System.out.println(array.get(3));//报错索引溢出,IndexOutOfBoundsException
**public int size():返回集合中元素的个数
System.out.println(array.size());//输出3
System.out.println("array:" + array);
}
}
案例:存储字符串并遍历
需求:创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合
遍历集合对象的通用格式:
for(int i = 0 ; i < 集合对象.size(); i ++){
集合对象.get(i)//指定索引处的元素
}
案例:
// 117
//案例:存储字符串并遍历
public class ArrayListTest1 {
public static void main(String[] args){
//需求:创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合
//创建一个集合,用于存储字符串
ArrayList<String> array = new ArrayList<String>();
//通过public boolean add(E element)添加字符串元素
array.add("time");
array.add("tries");
array.add("all");
array.add("things");
//通过for循环遍历该集合
//元素获取 通过public E get(int index)获取
//集合长度 通过public int size()获取
for(int i = 0; i<array.size(); i++){
if (i == array.size() - 1){
System.out.println(array.get(i));
}else{
System.out.print(array.get(i) + " ");
}
}
}
}
案例:存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合。
// 117
//存储学生对象并遍历
public class ArrayListDemo3 {
//需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合。
public static void main(String[] args){
//定义学生类
//在另一个文件中
//创建集合对象
ArrayList<Student> stu = new ArrayList<Student>();
//创建学生对象
Student st1 = new Student("汪苏泷",33);
Student st2 = new Student("许嵩",36);
Student st3 = new Student("徐良",35);
//添加学生对象到集合中
stu.add(st1);
stu.add(st2);
stu.add(st3);
//遍历集合,采用通用遍历格式实现
for (int i = 0 ; i < stu.size(); i ++){
Student s = stu.get(i);
System.out.println(s.getName() + ", " + s.getAge());
}
}
}
另一个文件的Student类
public class Student {
// 创建private 修饰的成员变量
private String name;
private int age;
// 创建无参、有参数的构造方法
public Student(){ }
public Student(String name,int age){
this.name = name;
this.age = age;
//这里的this指代对象,修改的是成员变量 private修饰的值
}
// 创建成员变量对应的get/set方法
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;
}
}
案例:存储学生对象并遍历升级版
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合。学生的姓名和年龄来自于键盘录入。
//117
//案例:存储学生对象并遍历升级版
public class ArrayListTest2 {
public static void main(String[] args){
// 需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合。学生的姓名和年龄来自于键盘录入.
//定义学生类,为了方便键盘录入,年龄和名字都定义为String类型
//另一个文件已创建
//创建集合对象
ArrayList<Student1> array = new ArrayList<Student1>();
//多次添加输入信息给学生对象,并将学生对象添加到集合中,使用for循环
/*for(int i = 0 ;i < 3 ; i++){
//键盘录入学生对象所需要的变量
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生的姓名:");
String stuName = sc.nextLine();
System.out.println("请输入学生的年龄");
String stuAge = sc.nextLine();
//创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
Student1 stu = new Student1(stuName,stuAge);
array.add(stu);
}*/
inputStudent(array);
inputStudent(array);
inputStudent(array);
System.out.println("-----------");
for(int i = 0; i<array.size();i++){
Student1 st = array.get(i);
System.out.println(st.getName() + ", " + st.getAge());
}
}
//使用方法实现
//两个明确:参数 ArrayList<Student1> 返回值 void
// 出错很多次了 方法不加static会报错
public static void inputStudent(ArrayList<Student1> array){
//键盘录入学生对象所需要的变量
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生的姓名:");
String stuName = sc.nextLine();
System.out.println("请输入学生的年龄");
String stuAge = sc.nextLine();
//创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
Student1 stu = new Student1(stuName,stuAge);
array.add(stu);
}
}
//Student1类
public class Student1 {
//成员变量
private String name;
private String age;
//构造方法
public Student1(){}
public Student1(String name,String age){
this.name = name;
this.age = age;
}
//set、get方法
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(String age){
this.age = age;
}
public String getAge(){
return age;
}
}
案例:学生成绩管理系统
注意事项:
1 System.exit(status:0);
可以实现java虚拟机(JVM)的退出;
2 类的构造方法的快捷键
alt + insert ,insert = 数字键盘 先按下num lock 再按下数字0
或者:
小键盘旁边的Ins也是insert的意思。
3 关于\t的使用
System.out.println("\t") 这样可以实现tab键的位置
4 关于return
为了让程序不再往下执行,给出return。
5 String.equals(String)
字符串的值比较
6 学号删除中学号不存在问题判断
通过
int index = -1;//用于标识学号是否存在与集合中
for(int i = 0;i<array.size();i++){
StudentM s = array.get(i);
if(s.getSid().equals(sid)){ // s.getSid 遍历每个集合元素的sid属性。sid是要删除的学生的学号
index = i;//存在于集合中,就修改index为对应的索引值
break;//跳出循环,不执行后续的比较
}
}
7 添加学生学号重复问题
通过方法判断:定义一个标识符flag标识学号是否重复》通过for循环遍历集合中元素,集合.get(index)获取集合元素》元素.getXxx()获取成员变量 》
学生学号 与 集合中对象的学号 进行比较,初始flag=-1,如果相同设置为flag设置为索引值。
public static int judgeSid(String sid,ArrayList<String> array){
int flag = -1;
for(int i = 0; i < array.size();i++){
if(array.get(i).getSid().equals(sid)){
// 学号重复,
flag = i;
}
}
return flag;
}
思路:
0 定义ArrayList集合存储学生对象 界面内容1添加2删除3修改4查看5退出 以及后续操作都存放在while死循环中。
while(true){
0 界面
0 获取要执行的功能编号 Scanner nextInt
采用switch语句将选择情况包起来,
1 添加学生 需要判重对于Sid
先输入学号,进行判重,如果flag=-1则没有重复,继续执行后续nextLine获取学生信息,创建对象,添加到集合(array.add(学生对象))
flag != -1 有重复,break;
2 删除学生 需要对Sid判断是否存在
先输入学号,进行判断是否存在,如果flag=-1则不存在,不执行删除
flag != -1 存在,执行array.remove(flag);
3 修改学生 需要对Sid判断是否存在
先输入学号,进行判断是否存在,如果flag=-1则不存在,不执行修改
flag != -1 存在,执行对应的 对象.setxxx()属性方法。
4 查看所有学生信息
for循环遍历,条件控制语句是 array.size(),
循环体是对象.getxxx()方法获得对象属性。
0 写Sid判重方法
public static int jugeSid(String sid,ArrayList<Student> array){
定义flag返回值,初始值是-1
for循环遍历集合,对每个元素的sid属性和参数sid进行比较,相同则将flag改为对一个的索引值,不同则不改。
循环控制条件 array.size()
if(array.get(i).getSid().equals(sid))
return flag
代码:
// 117
import java.util.ArrayList;
import java.util.Scanner;
//学生管理系统
public class StudentManager {
public static void main(String[] args) {
// 定义集合变量,用于存储学生
ArrayList<StudentM> array = new ArrayList<StudentM>();
//0主界面程序
//0-4 选择完成,使用循环再次回到主界面,注意选择5之后,程序要退出而不是再次回到主界面。
while (true) {
//0-1 通过sout输出语句搭建主界面提示信息
System.out.println("--------欢迎来到学生管理系统--------");
System.out.println("1 添加学生");
System.out.println("2 删除学生");
System.out.println("3 修改学生");
System.out.println("4 查看所有学生");
System.out.println("5 退出");
System.out.println("请输入你的选择:");
//0-2 用Scanner获取键盘录入信息
Scanner sc = new Scanner(System.in);
String select = sc.nextLine();
//0-3 使用switch分支实现对输入信息的判断,并执行对应操作
switch (select) {
case "1":
// System.out.println("添加学生");
addStudent(array);
break;
case "2":
// System.out.println("删除学生");
delectStudent(array);
break;
case "3":
// System.out.println("修改学生");
updataStudent(array);
break;
case "4":
// System.out.println("查看所有学生");
viewStudent(array);
break;
case "5":
System.out.println("谢谢使用");
//break;//单纯的break不能实现跳出while死循环,只可以跳出switch分支。
System.exit(0);//使用此语句可以实现JVM退出,java虚拟机都退出了,程序一定退出了。
default:
System.out.println("输入内容有误");
}
}
}
//1 添加学生信息
//返回值 void 参数ArrayList<StudentM> array
public static void addStudent(ArrayList<StudentM> array){
//思路一:没有考虑学号重复的问题。
/* //Scanner获取输入内容
Scanner sc = new Scanner(System.in);
//1-0 给出添加信息
System.out.println("请输入学生姓名:");
String name = sc.nextLine();
System.out.println("请输入学生学号:");
String sid = sc.nextLine();
System.out.println("请输入学生年龄");
String age = sc.nextLine();
System.out.println("请输入学生居住地:");
String address = sc.nextLine();
//1-1 创建学生对象,并将键盘录入的信息赋值给学生对象的成员变量
StudentM s = new StudentM();
s.setName(name);
s.setSid(sid);
s.setAge(age);
s.setAddress(address);
// 1-2 将学生对象添加到集合中
array.add(s);
// 1-3 给出添加学生信息成功提示
System.out.println("信息添加成功!");*/
//思路二:考虑学号重复问题。
//创建方法用于判断输入学号是否处于集合中 相同返回true,不同返回false
Scanner sc = new Scanner(System.in);
// 将sid定义在while循环之外,是为了后续学生对象调用set方法实现
String sid;
//为了保证输入学号错误之后还重新显示输入学生学号提示信息。
while(true) {
System.out.println("请输入学生学号:");
sid = sc.nextLine();
boolean flag = judgeSid(sid, array);
if (flag) {
System.out.println("输入学生的学号已被使用,请重新输入");
} else {
break;
}
}
System.out.println("请输入学生姓名:");
String name = sc.nextLine();
System.out.println("请输入学生年龄");
String age = sc.nextLine();
System.out.println("请输入学生居住地:");
String address = sc.nextLine();
//1-1 创建学生对象,并将键盘录入的信息赋值给学生对象的成员变量
StudentM s = new StudentM();
s.setName(name);
s.setSid(sid);
s.setAge(age);
s.setAddress(address);
// 1-2 将学生对象添加到集合中
array.add(s);
// 1-3 给出添加学生信息成功提示
System.out.println("信息添加成功!");
}
//2 删除学生
public static void delectStudent(ArrayList<StudentM> array){
// 此情况没有考虑 输入删除学号不存在的情况:
/* //2-0 输入要删除的学生的学号
Scanner sc = new Scanner(System.in);
System.out.println("请输入要删除的学生的学号");
String sid = sc.nextLine();
//2-1 利用循环遍历集合中元素找到对应的索引值,
for (int i = 0 ; i < array.size(); i++){
StudentM stu = array.get(i);
if(stu.getSid().equals(sid)){
//2-2 通过索引值使用remove方法删除学生对象
array.remove(i);
return;
}
}
//2-3 返回删除成功信息
System.out.println("删除成功");*/
// 考虑删除学号不存在的情况,需要提前判断学号是否存在
Scanner sc = new Scanner(System.in);
System.out.println("请输入要删除学生的学号:");
String sid = sc.nextLine();
int index = -1;
for (int i = 0 ; i < array.size(); i++){
StudentM s = array.get(i);
if(s.getSid().equals(sid)){
index = i;
break;
}
}
if(index == -1){
System.out.println("输入的学号有误,请重新输入");
}else{
array.remove(index);
System.out.println("删除成功!");
}
}
//3 修改学生
public static void updataStudent(ArrayList<StudentM> array){
//3-0 输入要修改的学生的学号
Scanner sc = new Scanner(System.in);
String sid;
while(true) {
System.out.println("请输入要修改的学生的学号:");
sid = sc.nextLine();
//避免修改学生信息,学生信息不存在的情况
boolean flag = judgeSid(sid, array);
if (!flag) {
System.out.println("输入的要修改的学生的学号不存在,请重新输入");
} else {
break;
}
}
//3-1 输入要修改的学生的 其他信息
System.out.println("请输入新的学生的姓名:");
String name = sc.nextLine();
System.out.println("请输入新的学生的年龄:");
String age = sc.nextLine();
System.out.println("请输入的新的学生的居住地");
String address = sc.nextLine();
// 思路一:通过方法学号找到它在集合中对应的索引 通过集合.get获取StudentM对象 然后通过对象.set方法重新赋值
// //3-2 遍历集合找到对应的索引值
// for(int i = 0; i<array.size();i++){
// //3-3 修改对应值
// StudentM s = array.get(i);
// if (s.getSid().equals(sid)) {
// s.setName(name);
// s.setAge(age);
// s.setAddress(address);
// }
// }
// //3-4 修改完成通知
// System.out.println("修改已完成");
//思路二:创建学生对象,通过键盘录入的信息
// 使用循环遍历,通过sid找到集合中对应对象的索引值,通过集合.set(int index,E element)方法
StudentM stu = new StudentM();
stu.setName(name);
stu.setAge(age);
stu.setSid(sid);
stu.setAddress(address);
for(int i = 0; i< array.size() ; i++){
StudentM s = array.get(i);
if(s.getSid().equals(sid)){
array.set(i, stu);
//成功之后就不再往后执行了。
break;
}
}
//输出修改成功提示
System.out.println("信息修改成功!");
}
//4 查看所有学生
public static void viewStudent(ArrayList<StudentM> array){
//判断集合中是否有内容 没有内容输出提示信息
//可以不适用if else语句实现。在if语句体中写return即可。
/* if(array.size() == 0){
System.out.println("没有学生信息,请添加!");
}else{
//显示表头信息
// \t 其实就是tab键的位置
System.out.println("学号\t姓名\t\t年龄\t\t居住地");
for(int i = 0 ;i <array.size(); i++){
StudentM stuM = array.get(i); //返回的是StudentM对象
System.out.println( stuM.getSid() + "\t\t" + stuM.getName() + "\t" + stuM.getAge() + "岁\t\t" + stuM.getAddress());
}
}*/
if(array.size() == 0){
System.out.println("没有学生信息,请添加!");
//为了不让程序往下执行,给出return;
return;
}
//显示表头信息
// \t 其实就是tab键的位置
System.out.println("学号\t姓名\t\t年龄\t\t居住地");
for(int i = 0 ;i <array.size(); i++){
StudentM stuM = array.get(i); //返回的是StudentM对象
System.out.println( stuM.getSid() + "\t\t" + stuM.getName() + "\t" + stuM.getAge() + "岁\t\t" + stuM.getAddress());
}
}
//1 用于判断学号重复的方法
public static boolean judgeSid(String sid , ArrayList<StudentM> array){
boolean flag = false;
for(int i = 0; i < array.size(); i++){
StudentM s = array.get(i);
if(s.getSid().equals(sid)){
flag = true;
break;
}
}
return flag;
}
}
LinkedList
概述
-
public class LinkedList< E > extends AbstractSequentialList< E > implements List< E > , Deque< E > , Cloneable,Serializable
-
继承自Deque
LinkedList类是双向链表,列表中的每个节点都包含对前一个和对后一个元素的引用。
LinkedList可以被当作堆栈、队列或者双端队列进行操作。
LinkedList本质是双向链表,包含两个重要成员:header 和 size 。- header是双向链表的表头,它是双向链表节点所对应的类Entry的实例。Entry中包含成员变量:previous、next、element。其中previous是该节点的上一个,next是该节点的下一个,element是该节点所包含的值。
- size是双向链表中节点的个数。
-
LinkedList的添加add操作,默认是队尾添加元素。
-
继承自Serializable
LinkedList实现了Serializable接口,所以可以被序列化,能通过序列化去传输。 -
LinkedList是非同步的。
构造函数
函数 | 说明 |
---|---|
LinkedList() | 默认构造函数 |
LinkedList(Collection<? extends E > collection) | 创建一个LinkedList,包含指定集合collection的全部元素 |
LinkedList集合的特有功能
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
public E pollLast() | 检索并删除此列表的最后一个元素,如果列表为空,返回null |
案例:
//215-LinkedListDemo
public class LinkedListDemo {
public static void main(String[] args){
LinkedList<String> list = new LinkedList<String>();
list.add("hello");
list.add("java");
list.add("world");
System.out.println(list);
list.addFirst("javaee");
//在集合首位添加元素
// 初始:[hello, java, world] 添加后:[javaee, hello, java, world]
list.addLast("javase");
//在集合尾部添加元素
// 初始:[hello, java, world] 添加后:[hello, java, world, javase]
System.out.println(list.getFirst());
// 返回集合首位元素 hello
// 初始:[hello, java, world]
System.out.println(list.getLast());
// 返回集合尾部元素 world
// 初始:[hello, java, world]
System.out.println(list.removeFirst());
//删除集合首位元素 并返回 hello
// 初始:[hello, java, world] 删除后: [java, world]
System.out.println(list.removeLast());
// 删除集合尾部元素并返回 world
// 初始:[hello, java, world] 删除后:[hello, java]
System.out.println(list);
}
}
LinkedList一般方法
方法名 | 说明 |
---|---|
E remove() | 检索并删除此列表的第一个元素 |
E remove(int index) | 删除该列表中指定位置的元素 index位置的元素 |
boolean remove(object o) | 从列表中删除指定元素第一个出现的 |
Vector类
概述
- Vector和ArrayList,底层采用的都是动态数组。
- Vector是有序的,可以存储重复值和null值。
- Vector是同步访问的,是有条件的线程安全;ArrayList,不是线程安全的;
- 初始容量是10,没有设置扩容增量的情况下以自身的2倍容量扩容,可以设置容量增量,初始容量和扩容量可以通过构造函数public Vector(int initialCapacity, int capacityIncrement)进行初始化。
- Vector适用情景:用在事先不知道数组的大小、或者需要一个可以改变大小的数组的情况。
构造方法
方法 | 说明 |
---|---|
Vector() | 创建一个默认大小是10的数组 |
Vector(int size) | 创建指定大小的数组 |
Vector(int size,int incr) | 创建指定大小的数组,并且增量用incr指定。增量表示向量每次增加的元素数目 |
Vector(Collection c) | 创建一个包含集合c元素的数组 |
列表迭代器ListIterator
概述
- Listiterator列表迭代器,通过List集合的listiterator()方法得到 列表迭代器ListIterator< E > ,它是一个List集合特有的迭代器
- ListIterator< E > 列表迭代器 软件包是 java.util,使用需要导包
- public interface ListIterator< E > extends Iterator 则说明ListIterator可以直接使用Iterator中的next和hasnext方法
- 迭代器没有当前所有元素一说,它只是一个游标(cursor)的概念,这个游标总是在元素之间。
- 列表迭代器的特点:
①允许沿任一方向遍历列表
②在迭代期间可以修改列表中的元素
③获取列表中迭代器的当前位置
常用方法
方法名 | 说明 |
---|---|
e next() | 返回游标后的元素, 同时将游标后移一位 |
e previous() | 返回游标前面的元素, 同时将游标前移一位 |
Boolean hasNext() | 判断游标后面是否有元素 |
Boolean hasPrevious() | 判断游标前面是否有元素 |
int nextIndex() | 返回游标后面元素的索引值,初始值是0; 遍历N个元素结束时是N |
int previousIndex() | 返回游标前面元素的索引值,初始值是-1, 同时报java.util.NoSuchElementException错 |
void add(e) | 在游标前插入一个元素 |
void set(e) | 更新迭代器最后一次操作的元素为E,更新最后一次调用next()或previous()返回的元素 当没有迭代,即没有执行next()或previous()时,直接使用set时会报 java.lang.illegalStateException错 |
void remove() | 删除迭代器最后一次操作的元素 当没有迭代,即没有执行next()或previous()时,直接使用remove时会报 java.lang.illegalStateException错 |
总结
最开始的list = 游标 you are my pretty sunshine
ListIterator<String> iter = list.listIterator();
代码 | list情况 | 输出结果 |
---|---|---|
iter.next | you 游标 my pretty sunshine | you |
iter.next iter.previous | you 游标 are my pretty sunshine 游标 you are my pretty sunshine | you you |
iter.next iter.nextIndex iter.PreviousIndex | you 游标 are my pretty sunshine | you 1 0 |
iter.next iter.add(e) | you 游标 are my pretty sunshine you e 游标 are my pretty sunshine | you void |
iter.next iter.set(e) | you 游标 are my pretty sunshine e 游标 are my pretty sunshine | you void |
iter.next iter.remove | you 游标 are my pretty sunshine 游标 are my pretty sunshine | you void |
案例
// 29-test1-ListIteratorDemo
public class ListIteratorDemo {
public static void main(String[] args){
List<String> list = new LinkedList<String>();
list.add("you");
list.add("are");
list.add("my");
list.add("pretty");
list.add("sunshine");
ListIterator<String> iter = list.listIterator();
// 使用增强for循环遍历集合
System.out.println("list集合");
for(String str:list){
System.out.print(str + " ");
}
System.out.println();
System.out.println("---------------");
// method7(iter);
// method8(iter,list);
method9(list);
}
// 测试iter.next
public static void method(ListIterator<String> iter){
System.out.println(iter.next());
// 第一次执行next 输出 you
// System.out.println(iter.next());
// 第二次执行next 输出are
}
// 测试游标在列表最开始的位置执行previous方法
public static void method2(ListIterator<String> iter){
System.out.println(iter.previous());
// 直接执行listIterator.previous 报错NoSuchElementException,因为初始值是-1
}
// 测试iter.next 和 iter.previous
public static void method3(ListIterator<String> iter){
System.out.println(iter.next());
System.out.println(iter.previous());
// 两者输出都是you,
// 执行next操作之前,游标的位置是{游标 you are my pretty sunshine},执行next操作,输出you,并将游标先后移动,游标位置{you 游标 are my pretty sunshine}
// 执行previous操作之前,游标位置{you 游标 are my pretty sunshine},所以游标前的数据是 you,并将游标前移,游标位置{游标 you are my pretty sunshine}
System.out.println(iter.next());
// // 输出结果还是you,游标位置{游标 you...},取游标后边的元素。
}
// 在最开始就执行nextIndex()
public static void method4(ListIterator<String> iter){
System.out.println(iter.nextIndex());
// 输出结果是0
// 执行nextIndex 之前没有执行next
}
// 册数nextIndex 和 previousIndex
public static void method5(ListIterator<String> iter){
iter.next();
System.out.println(iter.nextIndex());
// 输出结果是 1
System.out.println(iter.previousIndex());
// 输出结果是 0
}
// 测试set方法
public static void method6(ListIterator<String> iter){
iter.next();
iter.set("xhj");
// 修改了you的位置,此时集合元素是: xhj 游标 are
System.out.println(iter.previous());
// 输出的是 xhj
}
// 测试add方法
public static void method7(ListIterator<String> iter){
// 最开始 游标 you are
iter.next();
// 执行后 you 游标 are
iter.add("xhj");
// 在游标前插入元素 you xhj 游标 are
System.out.println(iter.previous());
// 输出xhj
}
// 测试remove方法
public static void method8(ListIterator<String> iter,List<String> list){
// 最开始 游标 you are
iter.next();
// 执行后 you 游标 are
iter.remove();
// 删除最近next.previous操作的元素
System.out.println(list);
}
获取ListIterator的方式
获取方式 | 说明 |
---|---|
list对象.listIterator() | 得到ListIterator对象 |
list对象.listIterator(int location) | 获得ListIterator对象且指定游标位置 location必须在[ 0,list对象.size() ) 表示游标list索引location前 |
案例:针对location索引问题
// 29-test1-ListIteratorDemo
List<String> list = new LinkedList<String>();
list.add("you");
list.add("are");
list.add("my");
list.add("pretty");
list.add("sunshine");
** 测试 List listIterator(int location) 查看location是否有界限
ListIterator<String> stringListIterator = list.listIterator(20);
System.out.println(stringListIterator.next());
//当索引超出list表长度的时候会报错。size是5,location是20
// IndexOutOfBoundsException
ListIterator<String> stringListIterator = list.listIterator(0);
System.out.println(stringListIterator.next());
// 索引是0,表示游标是在索引0的前面,则ListIterator.next会输出List的第一个元素
ListIterator<String> stringListIterator = list.listIterator(4);
System.out.println(stringListIterator.next());
// 索引是4,表示游标是在索引4的前面,则ListIterator.next会输出List的第5个元素
案例:使用iterator迭代器使用add方法会报错,但是ListIterator迭代器使用add不会报错
// 29
public class ListIteratorDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("java");
list.add("world");
// 通过ListIterator迭代器 遍历元素
// next hasNext
ListIterator<String> lit = list.listIterator();
// 此时游标的位置:游标 hello java world。
while(lit.hasNext()){
String s = lit.next();
System.out.println(s);
}
//依次输出 hello,java,world
System.out.println("---------------");
// 此时游标的位置:hello java world 游标
while(lit.hasPrevious()){
String s = lit.previous();
System.out.println(s);
}
//依次输出:world,java,hello
//获取列表迭代器 遍历列表,比较是否有world,有则添加javaee元素
ListIterator<String> lit2 = list.listIterator();
//使用iterator方法返回的Iterator迭代器,采用List集合对象的add方法添加元素会报错,
// 但是采用ListIterator迭代器的add方法则不会报错
while (lit2.hasNext()) {
String s = lit2.next();
if(s.equals("world")){
lit2.add("javaee");
}
}
System.out.println(list);
// [hello, java, world, javaee]
}
}
源码分析:
Iterator<String> it = list.iterator(); 分析步骤1
while (it.hasNext()) {
String s = it.next();
if(s.equals("world")){
list.add("javaee"); 分析步骤1
}
}
// 使用迭代器遍历集合元素会报错:ConcurrentModificationException
System.out.println(list);
//获取列表迭代器 遍历列表,比较是否有world,有则添加javaee元素
ListIterator<String> lit2 = list.listIterator();
//使用iterator方法返回的Iterator迭代器,采用List集合对象的add方法添加元素会报错,
// 但是采用ListIterator迭代器的add方法则不会报错
while (lit2.hasNext()) {
String s = lit2.next();
if(s.equals("world")){
lit2.add("javaee");
}
}
System.out.println(list);
// [hello, java, world, javaee]
分析代码:
list集合通过Iterator迭代器遍历集合,会报错;
list集合通过ListIterator迭代器遍历集合,不会报错;
原因是:
private class ListItr extends Itr implements ListIterator 返回的是ListIterator的实现类对象 = ListItr对象
ListIterator迭代器返回ListItr 的对象,ListItr 类中的add方法,有变量modCount 赋值给 exceptedModCount的语句,这样执行checkForComodification();的时候,判断modCount和exceptedModCount变量不相等输出ConcurrentModificationException 的情况不成立。
1 首先是List接口,接着使用接口中定义的两个方法:iterator、Listiterator、add
public interface List<E> {
Iterator<E> iterator();
ListIterator<E> listIterator();
}
2 创建对象,new的是ArrayList这个实现类的对象 来解释iterator 和 ListIterator 的 区别
** ArrayList集合继承自 AbstractList
public abstract class AbstractList<E>{
protected transient int modCount = 0;
// 此变量在AbstractList<E>类中
}
** ArrayList
public class ArrayList<E> extends AbstractList<E> implements List<E> {
// ArrayList实现了List这个接口,就需要重写List中的方法,例如:iterator、add、Listiterator
public ListIterator<E> listIterator() {
return new ListItr(0);
}
public Iterator<E> iterator() {
return new Itr();
}
private class ListItr extends Itr implements ListIterator<E> {
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();
}
}
}
增强for循环
作用:
简化数组和Collection集合的遍历
概述:
- Collection集合 继承自接口Iterable< E >
- 实现Iterable接口的类允许其对象成为增强型for语句的目标。
- 它是JDK5之后出现的,其内部原理是一个Iterator迭代器。
增强for格式
for(元素数据类型 变量名:数组或者Collection集合){
// 在此处使用变量即可,该变量就是元素
}
案例:
int[] arr = {1,2,3,4,5};
for(int i : arr){
System.out.println(i);
}
案例:元素类型是:int、String、List集合
int[] arr = {1,2,3,4,5};
for(int i : arr){
System.out.println(i);
}
//输出内容:1 2 3 4 5
System.out.println("----------");
String[] s = {"hello","java","world"};
for(String st : s){
System.out.println(st);
}
//输出内容:hello、java、world
System.out.println("--------");
List<String> list = new ArrayList<String>();
list.add("world");
list.add("java");
for(String str : list){
System.out.println(str);
}
// 输出内容:world java
证明:增强for循环的内部原理是一个Iterator迭代器
// 通过在for循环中 添加元素 看是否抛出并发异常
for(String str : list){
if(str.equals("world")){
list.add("javaee");
}
}
// 报错:抛出ConcurrentModificationException异常
案例:List集合存储学生对象三种方式遍历
// 29-test3
public class StudentDemo {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
Student s1 = new Student("汪苏泷",33);
Student s2 = new Student("易烊千玺",20);
Student s3 = new Student("胡夏",35);
list.add(s1);
list.add(s2);
list.add(s3);
//遍历元素
// 方式一:迭代器 collection.iterator 还有迭代器的方法hasNext、next
Iterator<Student> it = list.iterator();
while(it.hasNext()){
Student stu = it.next();
System.out.println(stu.getName() + ", " + stu.getAge());
}
System.out.println("1-----------");
// 方式二:普通的for循环 List.get list.size()
for(int i = 0 ; i< list.size(); i ++){
Student stu = list.get(i);
System.out.println(stu.getName() + ", "+stu.getAge());
}
System.out.println("2---------------");
// 方式三:增强for循环
for(Student stu : list){
System.out.println(stu.getName() + ", "+stu.getAge());
}
}
}