ArrayList 类 (顺序表)

news/2025/1/1 22:38:16/

目录

一. ArrayList 基本介绍

二. ArrayList 中的法及其应用

1. 添加元素

(1) add()

(2) addAll()

2. 删除元素

(1) remove()

(2) removeAll()

3. 遍历元素

(1) for 循环遍历

(2) for - each 遍历

(3) 迭代器遍历

(4) 列表迭代器遍历

4. 判断

(1) cotains()

(2) containsAll()

(3) isEmpty()

5. 获取子列表

三. 模拟实现 ArrayList

1. 模拟实现添加元素

2. 模拟实现删除元素

3. 模拟实现判断

4. 验证是否正确


一. ArrayList 基本介绍

(1) ArrayList (顺序表) 继承于 List接口, 是Java集合框架的一部分.

(2) ArrayList 用于存放可重复, 有序的元素.

(3) ArrayList 的存储结构是数组. (底层使用数组来实现).

(4) ArrayList提供了比标准数组更多的功能. 例如: 动态调整大小, 添加元素, 删除元素等.

(5) ArrayList 的特点是 查找 的速度快 (因为可以直接通过下标查找), 添加/删除 元素的速度慢.

二. ArrayList 中的法及其应用

通过查看文档我们可以看到, List 接口主要有以上几种方法. 我把其中比较重要的几个方法勾选了出来, 这些我们要重点熟悉掌握. 大家也可以自行翻阅文档进行学习. 

首先我们要在list里存放对象. 假设我们要存放Student类型的对象.

首先定义学生类:

java">public class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object obj) {if (this == obj) {  //1. 如果this和obj指向同一个对象, 则返回true;return true;}if (obj instanceof Student) {  //2. 如果this和obj指向不同对象, 而且obj是Student类型的if (this.age == ((Student) obj).getAge() && this.name == ((Student) obj).getName()) {return true;}return false;}return false;}
}

1. 添加元素

(1) add()

add() 方法, 有两个版本: 版本一有一个参数, 版本二有两个参数. 

[1] add(E e)  将指定元素添加到末尾

java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList);}
}

 

[2] add(int index, E element)  将指定元素插入指定位置.

java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList);Student s4 = new Student("Jack",45);arrayList.add(1,s4);System.out.println(arrayList);}
}

(2) addAll()

addAll() 方法的基本作用是将一个列表添加到另一个列表中去. 与add() 类似, addAll() 方法也有两个版本:

[1] addAll(Collection e) 表示将另一列表添加到当前列表之后.

java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList); // 打印arrayListStudent s4 = new Student("Jack",45);Student s5 = new Student("Bob", 55);Student s6 = new Student("Molly",31);ArrayList<Student> arrayList1 = new ArrayList<>();arrayList1.add(s4);arrayList1.add(s5);arrayList1.add(s6);System.out.println(arrayList1); // 打印arrayList1arrayList.addAll(arrayList1);System.out.println(arrayList); // 打印合并之后的arrayList}
}

 [2] addAll(intindex, Collection e) 表示在指定位置插入另一列表.

java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList);Student s4 = new Student("Jack",45);Student s5 = new Student("Bob", 55);Student s6 = new Student("Molly",31);ArrayList<Student> arrayList1 = new ArrayList<>();arrayList1.add(s4);arrayList1.add(s5);arrayList1.add(s6);System.out.println(arrayList1);arrayList.addAll(1,arrayList1);System.out.println(arrayList);}
}

2. 删除元素

(1) remove()

remove() 方法, 参数可以传递下标, 也可以传递对象的引用. 作用都是把指定节点删除掉. 代码演示如下:

java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList);arrayList.remove(0); // 传递下标删除元素System.out.println(arrayList);arrayList.remove(s2); // 传递对象删除元素System.out.println(arrayList);}
}

(2) removeAll()

与add()和addAll()的关系类似, remove()方法是删除单个元素, removeAll()方法是从一个列表里删除另一个列表中的所有元素.

因为我们在Student里重写了equals()方法, 所以只要两个对象的name和age属性一样, 那么就认为这两个对象是相同的.

java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList);Student s4 = new Student("Jack",45);Student s5 = new Student("Bob", 55);Student s6 = new Student("Molly",31);ArrayList<Student> arrayList1 = new ArrayList<>();arrayList1.add(s1);arrayList1.add(s2);System.out.println(arrayList1);arrayList.removeAll(arrayList1);System.out.println(arrayList);}
}

3. 遍历元素

(1) for 循环遍历
java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);for (int i = 0; i < arrayList.size(); i++) {System.out.println(arrayList.get(i));}}
}

(2) for - each 遍历
java">import java.util.ArrayList;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);for (Student stu: arrayList) {System.out.println(stu);}}
}

(3) 迭代器遍历
java">import java.util.ArrayList;
import java.util.Iterator;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);Iterator<Student> iterator = arrayList.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

(4) 列表迭代器遍历
  • 正序遍历:
java">import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);ListIterator<Student> iterator = arrayList.listIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

  • 逆序遍历: 
java">import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;public class demo {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);ListIterator<Student> iterator = arrayList.listIterator(arrayList.size()); // 相当于把迭代器插入到 size() 位置的前面. 从这里开始遍历while (iterator.hasPrevious()) {System.out.println(iterator.previous());}}
}

[注]: 这里我们需要注意一点:  给 listIterator() 传参数 就表示将迭代器插入到index位置的前面

 所以这里给listIterator() 传了一个arrayList.size(), 就相当于把迭代器插入到了 size() 位置的前面

4. 判断

(1) cotains()
java">public class demo1 {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList.contains(new Student("吴彦祖", 26)));System.out.println(arrayList.contains(new Student("周润发", 50)));}
}

(2) containsAll()
java">import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;public class demo1 {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);ArrayList<Student> arrayList1= new ArrayList<>();arrayList1.add(s1);arrayList1.add(s2);System.out.println(arrayList.containsAll(arrayList1));}
}

(3) isEmpty()

判断当前顺序列表是否为空.

java">import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;public class demo1 {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);System.out.println(arrayList.isEmpty());arrayList.clear();System.out.println(arrayList.isEmpty());}
}

5. 获取子列表

ArrayList中, 获取一个顺序列表的子列表, 需要使用 subList() 方法

subList() 方法, 参数传一个区间(左闭右开), 表示要获取的子列表的区间.

java">import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;public class demo1 {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);Student s4 = new Student("大师",99);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);arrayList.add(s4);System.out.println(arrayList);List<Student> sl = arrayList.subList(1,3); //获取区间[1,3) 左闭右开.System.out.println(sl);}
}

6. 获取下标

ArrayList中, 获取下标使用 indexOf() 方法:

java">public class demo2 {public static void main(String[] args) {Student s1 = new Student("刘德华",22);Student s2 = new Student("梁朝伟",24);Student s3 = new Student("吴彦祖",26);Student s4 = new Student("大师",99);ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(s1);arrayList.add(s2);arrayList.add(s3);arrayList.add(s4);System.out.println(arrayList.indexOf(s2));System.out.println(arrayList.indexOf(s3));}
}

三. 模拟实现 ArrayList

我们知道, Arraylist底层是基于数组实现的. 所以, 我们在模拟实现Arraylist的时候,, 就需要先创建于一个数组, 然后基于数组实现我们自己的Arraylist.

为了实现起来简单, 我们自己实现ArrayList只能存放 int 类型的元素.

java">public class MyArrayList {public int[] elem; //定义一个操作数组public int usedSize; //定义一个 "已使用空间"public MyArrayList() {this.elem = new int[10];}
}

如上图, 这是就是模拟顺序列表中的属性, 一个是数组elem(在创建对象时 被初始化为10) , 另一个是usedSize, 表示已使用空间 (也就是数组中的元素个数 / 数组的长度).

还有一个问题, 因为我们验证我们写的方法是否正确时 要打印数组, 所以我们还需要重写一下 toString 方法, 否则打印出来的一堆哈希码, 没有可读性.

java">    @Overridepublic String toString() {String str = "";for (int i = 0; i < size(); i++) {if (i == 0){str += "[";str += elem[i];str += ",";continue;}if (i == size()-1) {str += elem[i];str += "]";continue;}str += elem[i];str += ",";}return str;}

1. 模拟实现添加元素

判满方法:

java">    private boolean isFull () {if (usedSize == elem.length) {return true;}else {return false;}}
(1) 添加元素到末尾 
java">public void add(int data) { //添加元素到末尾.if (this.isFull()) { //如果数组满了, 对数组进行扩容.elem = Arrays.copyOf(elem, 2*elem.length);}elem[usedSize] = data;usedSize ++;}

先判断数组是不是满了: 如果满了, 就扩容; 如果没满, 就进行添加元素操作.

(2) 添加元素到指定位置
java">public void add(int index, int data) { // 添加元素到指定位置.if (this.isFull()) {elem = Arrays.copyOf(elem, 2*elem.length);}for (int i = size()-1; i >= index; i--) {elem[i+1] = elem[i]; // 把元素向后移一位.(把i位置的元素赋到它后面的位置)}elem[index] = data;usedSize++;}

 相同地, 我们还是先判断是不是数组满的: 如果满了, 就扩容; 如果没满, 就进行添加元素操作.

这里由于是添加到指定位置, 所以原先在指定位置的元素及其后面的所有元素就需要后移.

2. 模拟实现删除元素

获取列表长度方法:

java">  public int size() { // 求当前顺序表的长度.return this.usedSize;}
(1) 根据值删除元素
java">   public void remove (int data) {  //根据值删除元素for (int i = 0; i < size(); i++) { //先找到指定元素的下标if (elem[i] == data) {for (int j = i; j < size()-1; j++) {elem[j]= elem[j+1]; // 往前覆盖掉elem[i].}usedSize--;}}}

这里需要注意的点是: 删除元素 就是把指定元素的位置覆盖掉就可以了.

(2) 根据下标删除元素
java">    public void  removeIndex (int index) { // 根据下标删除元素for (int j = index; j < size()-1; j++) {elem[j] = elem[j+1];}usedSize--;}

3. 模拟实现判断

(1) contains
java">public boolean contains(int data) { // 判断是否包含指定元素datafor (int i = 0; i < size(); i++) {if (elem[i] == data) {return true;}}return false;}
(2) isEmpty()
java">public boolean isEmpty() {  //判断当前顺序列表是否为空if (this.usedSize == 0) {return true;}else {return false;}}
(3) clear()
java">public void clear() { // 清空当前顺序列表.this.usedSize = 0;}

4. 验证是否正确

java">public class Main {public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();//1. 验证add (添加到元素末尾)myArrayList.add(1);myArrayList.add(1);myArrayList.add(2);myArrayList.add(3);myArrayList.add(4);myArrayList.add(5);System.out.println(myArrayList);//2. 验证 add (添加到指定位置)myArrayList.add(2,99);System.out.println(myArrayList);//3. 验证 remove (根据值删除元素)myArrayList.remove(2);System.out.println(myArrayList);//4. 验证 remove (根据下标删除元素)myArrayList.removeIndex(1);System.out.println(myArrayList);//5. 验证 containsSystem.out.println(myArrayList.contains(99));//6. 验证 isEmpty() 和 clear()System.out.println(myArrayList.isEmpty());myArrayList.clear();System.out.println(myArrayList.isEmpty());}
}

通过打印结果我们发现, 我们模拟实现的 ArrayList 没有任何问题~~ 


http://www.ppmy.cn/news/1557753.html

相关文章

【C++——迭代器】

概述 迭代器用在顺序容器中&#xff0c;比如&#xff1a;list&#xff0c;vector&#xff0c;map这些。 迭代器和指针用法类似&#xff0c;可以用*解引用&#xff0c;但是本质上不是指针。 迭代器类型&#xff1a; 常量迭代器只能读容器&#xff0c;不能改。但是迭代器自身还…

游戏引擎学习第57天

仓库&#xff1a;https://gitee.com/mrxiao_com/2d_game 回顾 目前正在处理的是关于游戏结构的核心部分&#xff0c;主要包括如何存储、更新以及追踪世界中的实体&#xff0c;以及实体之间如何交互等内容。这是开发中一个非常重要的环节&#xff0c;直接影响到后续的游戏功能…

【FFmpeg】万能的视频处理工具使用教程(持续更新)

一、FFmpeg简介及应用场景 FFmpeg是一套由c语言编写的,自身采用LGPL或GPL许可证,免费开源的音视频处理工具库,可以实现音视频格式转换、编解码、流媒体处理等功能。 FFmpeg支持的视频格式包括MPEG4、AVI、WMV、FLV、H.264等等,支持的音频格式包括MP3、WMA、AAC、AMR等等。…

有哪些其他方法可以实现数据一致性验证?

数据库约束 主键约束&#xff1a; 主键是表中用于唯一标识每条记录的一列或一组列。例如&#xff0c;在一个“用户表”中&#xff0c;用户ID可以作为主键。当插入或更新数据时&#xff0c;数据库会自动检查主键值是否唯一。如果试图插入一个已存在主键值的记录&#xff0c;数据…

【PyCharm】

Mac M1 一、使用 1、Python 环境配置 PyCharm ⇒ Settings ⇒ Project:pythonProject ⇒ Python Interpreter ⇒ Add Interpreter ⇒ Add Local Interpreter 可添加本地文件 使用conda 二、插件整合 1、汉化与取消汉化 汉化&#xff1a;PyCharm ⇒ Settings ⇒ Plugins …

Nginx IP优化限制策略

Nginx 如何限制每个 IP 地址的连接数&#xff0c;优化资源分配&#xff1f; Nginx 限制每个 IP 地址的连接数 Nginx 提供了多种机制来限制单个 IP 地址所能建立的同时连接数&#xff0c;这对于防止资源耗尽和提高服务稳定性至关重要。以下是几种有效策略&#xff1a; 1. 使用…

【CSS】优化动画性能

最核心要开启gpu加速。 建议使用requestAnimationFrame&#xff0c;如果用js修改元素的位置&#xff0c;推荐使用这个API。 定时器时间不准确&#xff0c;requestAnimationFrame 始终在当前帧的最后执行。 利用css3 translate进行元素移动 在 CSS3 中&#xff0c;可以使用 tr…

MATLAB里面,try-catch-end系列语言的含义与用法(含例程)

在 MATLAB 中&#xff0c;try-catch-end 语句用于处理可能会引发错误的代码。它允许你在“尝试”部分执行代码&#xff0c;如果代码执行过程中发生错误&#xff0c;将转到“捕获”部分执行相应的处理。这种错误处理机制可以提高程序的健壮性&#xff0c;避免因小错误导致整个程…