前言:
顺序表是属于数据结构的一种。其实在Java中很多的数据结构类型是被实现了的(在C语言中没有被实现),本期作品将深入探讨Java中ArrayList的实现原理、常用操作以及一些使用场景。
liangzai比代码更鲜活
我的主页:_liangzai
欢迎大家访问~~
创作不易,点赞关注鼓励一下吧~~
先让我们看一下本期讲解的大体内容:
- 初识顺序表
- 顺序表的创建
- 顺序表的遍历
- 手动实现顺序表的各种功能
1.初始顺序表
在了解顺序表的定义之前,我们需要先了解一下什么是线性表:
线性表,全名为线性存储结构。使用线性表存储数据的方式可以这样理解,即“把所有数据用一根线儿串起来,再存储到物理空间中”,在逻辑上一定连续,但在物理上不一定连续。
在了解完线性表的概念之后,我们在来看顺序表:
(1)顺序表的定义
数据结构在内存中的表示通常有两种形式,一种是顺序存储,另一种是链式存储。线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表的数据元素,我们把这种存储形式存储的线性表称为顺序表。
ArrayList是一个普通的类,实现了List接口,具体框架图如下:
例如,使用顺序表存储集合 {12,23,34,45},数据最终的存储状态如图 1 所示:
由上图可知顺序表存储数据同数组非常接近。其实,顺序表存储数据使用的就是数组。(不同的是顺序表可以便捷调用一些功能)。
(2)顺序表的特点
- 顺序表的逻辑结构和物理结构是一致的,都是连续的。
- 顺序表中任意一个数据元素都可以随机存取,所以顺序表是一种随机存取的存储结构。
2.顺序表的创建
了解完了Java中ArrayList(顺序表),那么我们如何去创建并使用它呢?在Java中给我们提供了三种创建ArrayList的方式。
创建方式 | 解析 |
---|---|
ArrayList() | 无参构造 |
ArrayList(int initialCapacity) | 指定顺序表初始容量 |
ArrayList(Collection<? extends E> c) | 利用其他 Collection 构建 ArrayList |
现在让我们使用三种不同的方式来创建一下ArrayList(顺序表):
(1)使用默认构造函数创建一个空的 ArrayList:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个空的 ArrayList
ArrayList<String> list = new ArrayList<>();
// 添加元素到 ArrayList(这里可以先看一下就可以)
list.add("liangzai");
list.add("xiaohu");
list.add("xiaozhuang");
list.add("xincheng");
// 打印 ArrayList
System.out.println("ArrayList 1: " + list);
}
(2)使用带有初始容量的构造函数创建 ArrayList:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个具有初始容量的 ArrayList
ArrayList<Integer> list = new ArrayList<>(5);//初始容量为5
// 添加元素到 ArrayList(这里先看一下就可以)
list.add(10);
list.add(20);
list.add(30);
// 打印 ArrayList
System.out.println("ArrayList 2: " + list);
}
}
(3)使用 ArrayList(Collection<? extends E> c) 构造函数创建 ArrayList 的简单示例:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 创建一个包含初始元素的集合
List<String> originalList = new ArrayList<>();
originalList.add("liangzai");
originalList.add("xincheng");
originalList.add("xiaohu");
// 使用原始集合创建一个新的 ArrayList
ArrayList<String> newList = new ArrayList<>(originalList);
// 打印新的 ArrayList
System.out.println("New ArrayList: " + newList);
}
}
这就是Java中创建ArrayList的三种方法。
3.顺序表的遍历
在认识ArrayList的段落中,我们知道了ArrayList的底层是一个动态数组,既然是数组的话,我们是不是可以像遍历数组一样遍历ArrayList呢?答案是——可以的,但是在此之上我们还可以使用迭代器对其进行遍历。
遍历ArrayList的三种方式
- 使用for循环
- 使用加强型for循环
- 使用迭代器
(1)使用for循环
for (int i = 0; i < list.size(); i++) {
int element = list.get(i);
System.out.println(element);
}
(2)使用加强型for循环
for (int element : list) {
System.out.println(element);
}
(3)使用迭代器
//Integer为int的包装类
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
int element = iterator.next();
System.out.println(element);
}
以上就是三种遍历Java中ArrayList的方式,每种方式都有其适用的场景,我们可以根据实际需求选择最合适的方式来遍历ArrayList对象。
4.手动实现顺序表的各种功能
接下来我们自己来实现一下下面的8个功能
// 新增元素,默认在数组最后新增
public void add(int data);
// 在 pos 位置新增元素
public void add(int pos, int data);
// 判定是否包含某个元素
public boolean contains(int toFind);
// 查找某个元素对应的位置
public int indexOf(int toFind);
// 获取 pos 位置的元素
public int get(int pos);
// 给 pos 位置的元素设为 value
public void set(int pos, int value);
//删除第一次出现的关键字key
public void remove(int toRemove);
// 清空顺序表
public void clear();
新增元素(默认在数组最后新增)
我们直接使用代码来看一下:
public void add(int data) {
//isFull方法是判断ArrayList是否已满
if(isFull()){
//满了则扩容
grow();
}
arr[useSize] = data;
//useSize表示ArrayList中的有效元素个数
useSize++;
}
此方法会在顺序表的末尾加入元素。额外增加了判满和扩容两个方法。(可以去我的gitee上看我的完整代码—liangzai)
在指定位置新增元素
我们直接使用代码来看一下:
public void add(int pos, int data) {
try {
//此处判断pos位置是否违法
checkpos(pos);
if (isFull()) {
grow();
}
for (int i = useSize - 1; i >= pos; i--) {
this.arr[i + 1] = arr[i];
}
arr[pos] = data;
useSize++;
//在这里我们自定义了一个异常
}catch (PosException e){
System.out.println("pos位置不合法!");
e.printStackTrace();
}
}
此方法可以在指定位置增加元素。这里有两点,第一我们创建了一个判断pos位置是否合法,第二对于pos位置不合法我们自定义一个异常去解决它。
包含某个元素
我们直接使用代码来看一下:
public boolean contains(int toFind) {
for (int i = 0; i < useSize; i++) {
if(arr[i]==toFind){
return true;
}
}
return false;
}
此方法可以判断ArrayList中是否有toFind元素,有返回true,无则返回false。
查找元素位置
我们直接使用代码来看一下:
public int indexOf(int toFind) {
for (int i = 0; i < useSize; i++) {
if(arr[i] == toFind){
return i;
}
}
return -1;
}
此方法可以找到toFind第一个元素的下标位置。
获取 pos 位置的元素
我们直接使用代码来看一下:
public int get(int pos) {
try{
//此处判断pos位置是否违法
checkpos2(pos);
return this.arr[pos];
//自定义异常
}catch(PosException e){
System.out.println("pos位置不合法!");
e.printStackTrace();
return -1;
}
}
此方法可以找到指定位置的元素。这里有两点(同上)。
更改元素
我们直接使用代码来看一下:
public void set(int pos, int value) {
try{
//此处判断pos位置是否违法
checkpos2(pos);
checkList();
arr[pos] = value;
//自定义异常
}catch(PosException e){
System.out.println("pos位置不合法!");
e.printStackTrace();
//自定义异常
}catch (ListException e){
System.out.println("顺序表为空!");
e.printStackTrace();
}
此方法用于更改pos位置的元素。这里新增一个“顺序表为空”的自定义异常。
–
删除元素
我们直接使用代码来看一下:
public void remove(int toRemove) {
try {
checkList();
int pos = indexOf(toRemove);
if (pos == -1) {
System.out.println("此元素不存在!");
return;
}
if (pos == arr.length - 1) {
arr[pos] = 0;
} else {
for (int i = pos; i < useSize - 1; i++) {
arr[i] = arr[i + 1];
}
arr[useSize - 1] = 0;
}
useSize--;
}catch (ListException e){
System.out.println("顺序表为空!");
e.printStackTrace();
}
此方法先要判断此元素是否存在,然后在删除此元素。
清空顺序表
我们直接使用代码来看一下:
public void clear() {
if(useSize==0){
return ;
}
for (int i = useSize-1; i >= 0 ; i--) {
arr[i] = 0;
}
useSize=0;
}
通过遍历整个顺序表将每个元素置为0。
这样我们就使用Java手动的实现了ArrayList的常用功能。
想看源码可以进入作者的gitee查看-----liangzai
完结
好了,这期的分享到这里就结束了~
如果这篇博客对你有帮助的话,可以点一个免费的赞并收藏起来~
后面作者将持续更新blog,希望能够得到大家的支持~