当前位置: 首页 > news >正文

java数据结构--ArrayList与顺序表

一、线性表

线性表是一种最基本的数据结构,它是由 n 个具有相同特性的数据元素组成的有限序列。线性表的特点是:除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继。

生活中很多场景都可以抽象为线性表,比如排队的人群(每个人前面只有一个人,后面也只有一个人)、电话号码簿(按顺序排列的联系人)等。

二、顺序表

顺序表是线性表的一种实现方式,它用一段物理地址连续的存储单元依次存储线性表的数据元素。简单来说,就是在内存中开辟一块连续的空间,把数据按顺序存进去。

2.1.接口的实现

public interface MyList {// 新增元素void add(int data);// 在指定位置插入元素void add(int index, int data);// 删除指定位置元素int remove(int index);// 获取指定位置元素int get(int index);// 修改指定位置元素void set(int index, int data);// 查找元素位置int indexOf(int data);// 判断是否包含元素boolean contains(int data);// 获取元素个数int size();// 判断是否为空boolean isEmpty();// 清空所有元素void clear();
}

顺序表的实现依靠数组完成,通过维护一个数组和当前元素个数来管理数据。其优势是随机访问效率高(通过索引直接访问),但插入和删除操作可能需要移动大量元素,效率较低。

三、ArrayList简介

ArrayList 是 Java 集合框架中 List 接口的一个实现类,本质上是一个动态数组。与普通数组相比,它的容量可以动态增长,无需在创建时就确定大小,极大地提升了使用的灵活性。

ArrayList 的底层是用数组实现的,当元素数量超过当前容量时,会自动进行扩容操作。它允许存储 null 值,也允许存储重复元素,并且是有序的(存储顺序与插入顺序一致)。

需要注意的是,ArrayList 不是线程安全的,在多线程环境下使用需要额外处理线程安全问题(可以使用Collections.synchronizedList()方法包装,或使用CopyOnWriteArrayList)。

四、ArrayList使用

4.1.ArrayList的构造

ArrayList 提供了三种常用的构造方法:

1.无参构造:

创建一个初始容量为 0 的 ArrayList,首次添加元素时会扩容到默认容量(10)

List<String> list1 = new ArrayList<>();

2.指定初始容量的构造:

创建一个指定初始容量的 ArrayList,适合提前知道大致元素数量的场景,可减少扩容次数

List<Integer> list2 = new ArrayList<>(20);

3.用已有集合创建:

将其他集合中的元素初始化到 ArrayList 中

List<Character> list3 = new ArrayList<>(Arrays.asList('a', 'b', 'c'));

4.2.ArrayList常见操作

ArrayList 提供了丰富的操作方法,以下是常用的一些:

方法
解释
boolean add(E e)
尾插 e
void add(int index, E element)
e 插入到 index 位置
boolean addAll(Collection<? extends E> c)
尾插 c 中的元素
E remove(int index)
删除 index 位置元素
boolean remove(Object o)
删除遇到的第一个 o
E get(int index)
获取下标 index 位置元素
E set(int index, E element)
将下标 index 位置元素设置为 element
void clear()
清空
boolean contains(Object o)
判断 o 是否在线性表中
int indexOf(Object o)
返回第一个 o 所在下标
int lastIndexOf(Object o)
返回最后一个 o 的下标
List<E> subList(int fromIndex, int toIndex)
截取部分 list
public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("JavaSE");list.add("JavaWeb");list.add("JavaEE");list.add("JVM");list.add("测试课程");System.out.println(list);// 获取list中有效元素个数System.out.println(list.size());// 获取和设置index位置上的元素,注意index必须介于[0, size)间System.out.println(list.get(1));list.set(1, "JavaWEB");System.out.println(list.get(1));// 在list的index位置插入指定元素,index及后续的元素统一往后搬移一个位置list.add(1, "Java数据结构");System.out.println(list);// 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置list.remove("JVM");System.out.println(list);// 删除list中index位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常list.remove(list.size()-1);System.out.println(list);// 检测list中是否包含指定元素,包含返回true,否则返回falseif(list.contains("测试课程")){list.add("测试课程");}// 查找指定元素第一次出现的位置:indexOf从前往后找,lastIndexOf从后往前找list.add("JavaSE");System.out.println(list.indexOf("JavaSE"));System.out.println(list.lastIndexOf("JavaSE"));// 使用list中[0, 4)之间的元素构成一个新的SubList返回,但是和ArrayList共用一个elementData数组List<String> ret = list.subList(0, 4);System.out.println(ret);list.clear();System.out.println(list.size());
}

4.3.ArrayList的遍历

ArrayList 有三种常用的遍历方式:

1.普通 for 循环:适合需要索引的场景

for (int i = 0; i < fruits.size(); i++) {System.out.println(fruits.get(i));
}

2.增强 for 循环(foreach):简洁,无需关心索引

for (String fruit : fruits) {System.out.println(fruit);
}

3.迭代器(Iterator):支持在遍历中安全删除元素

Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {String fruit = iterator.next();if ("apple".equals(fruit)) {iterator.remove(); // 安全删除}
}

4.4.ArrayList的扩容机制

ArrayList 的扩容机制是其核心特性之一,理解它有助于更好地使用 ArrayList:

  1. 初始容量:无参构造创建的 ArrayList 初始容量为 0,首次添加元素时会扩容到 10
  2. 扩容触发:当元素数量达到当前容量时,触发扩容
  3. 扩容规则:扩容后的新容量 = 旧容量 + 旧容量 / 2(即 1.5 倍扩容)
  4. 特殊情况:如果计算的新容量小于最小需求容量,则直接使用最小需求容量
public static void main(String[] args) {List<Integer> list = new ArrayList<>();for (int i = 0; i < 100; i++) {list.add(i);}
}
ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容。以下是ArrayList源码中扩容方式:
扩容的本质是创建一个更大的新数组,然后将旧数组中的元素复制到新数组中,这个过程是比较耗时的。因此,在已知元素大致数量的情况下,建议使用指定初始容量的构造方法,以减少扩容次数,提高性能。

五、ArrayList的具体使用

5.1.简单的洗牌算法

利用 ArrayList 可以实现一个简单的洗牌算法,将一组牌随机打乱顺序:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class ShuffleDemo {public static void main(String[] args) {// 初始化一副牌(1-54,代表54张牌)List<Integer> cards = new ArrayList<>(54);for (int i = 1; i <= 54; i++) {cards.add(i);}// 洗牌:从最后一张牌开始,与前面随机位置的牌交换Random random = new Random();for (int i = cards.size() - 1; i > 0; i--) {// 生成0到i之间的随机索引int j = random.nextInt(i + 1);// 交换元素int temp = cards.get(i);cards.set(i, cards.get(j));cards.set(j, temp);}System.out.println("洗牌后:" + cards);}
}

洗牌算法的核心思想是从最后一个元素开始,依次与前面随机位置的元素交换,这样可以保证每个元素出现在每个位置的概率相等。

5.2.杨辉三角

杨辉三角是中国古代数学的杰出研究成果之一,其特点是每行的第一个和最后一个元素都是 1,其余元素等于它上方两元素之和。使用 ArrayList 可以方便地生成杨辉三角:

import java.util.ArrayList;
import java.util.List;public class YanghuiTriangle {public static void main(String[] args) {int numRows = 5; // 生成5行杨辉三角List<List<Integer>> triangle = generate(numRows);// 打印杨辉三角for (List<Integer> row : triangle) {System.out.println(row);}}public static List<List<Integer>> generate(int numRows) {List<List<Integer>> result = new ArrayList<>();// 第一行始终是[1]result.add(new ArrayList<>());result.get(0).add(1);// 生成后续行for (int i = 1; i < numRows; i++) {List<Integer> prevRow = result.get(i - 1);List<Integer> currRow = new ArrayList<>();// 每行的第一个元素是1currRow.add(1);// 中间元素 = 上一行相邻两元素之和for (int j = 1; j < i; j++) {currRow.add(prevRow.get(j - 1) + prevRow.get(j));}// 每行的最后一个元素是1currRow.add(1);result.add(currRow);}return result;}
}
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]

通过嵌套的 ArrayList 结构,我们可以很自然地表示杨辉三角的行与列关系,每行的元素个数与行号(从 0 开始)相等,实现起来非常直观。

ArrayList 作为 Java 中最常用的集合类之一,基于顺序表的思想实现,提供了动态扩容的功能,兼顾了数组的随机访问效率和链表的动态容量特性。

六、总结

在实际开发中,合理使用 ArrayList 需要注意:

  • 根据元素数量预估初始容量,减少扩容开销
  • 遍历方式根据场景选择(需要索引用普通 for,删除元素用迭代器)
  • 多线程环境下注意线程安全问题

掌握 ArrayList 的原理和使用技巧,能帮助我们更高效地处理数据集合,写出更优质的代码。

http://www.dtcms.com/a/507140.html

相关文章:

  • 【IEEE/EI/Scopus检索】2026年IEEE第七届计算,网络与物联网国际会议(CNIOT 2026)
  • 大数据计算引擎-Hudi对Spark Catalyst 优化器的RBO、CBO做了什么
  • 设计模式之:建造者模式
  • 阿里云 RDS MySQL 可观测性最佳实践
  • 【含文档+PPT+源码】基于spring boot的固定资产管理系统
  • 企业门户网站建设新闻柳州seo培训
  • 广东长海建设工程有限公司网站众筹网站建设报价
  • 航运、应急、工业适用,AORO P1100三防平板引领行业数字化变革
  • Linux网络:UDP
  • vue3知识点-ref和reactive以及toRefs与toRef
  • 环保网站 源码wordpress展示页
  • NSSCTF - Web | 【第五空间 2021】pklovecloud
  • 了解“网络协议”
  • ECharts 实时数据平滑更新实践(含 WebSocket 模拟)
  • ImmutableList.of() 是 Google Guava 库 提供的一个静态工厂方法,用于创建一个不可变的(immutable)列表。
  • 【计算机网络】408考研计算机网络精讲:物理层核心——信道的极限容量(奈氏准则与香农定理)​​
  • 嵌入式模组拨号获取IP地址时,设置的ippass是什么原理,起到什么作用?
  • 网站开发 实训 报告郑州高端建站公司
  • 2025年--Lc203- 1218. 最长定差子序列(动态规划)--Java版
  • TDengine
  • 【MicroPython编程-ESP32篇】-L298N控制直流电机
  • C# 设计模式——单例模式
  • 单例模式与线程池的实际应用
  • Ubuntu24 逻辑卷磁盘扩容全流程
  • 网站加载速度慢的原因佛山网站建设公司价格
  • 容器化与调度:使用 Docker 与 K8s 管理分布式淘宝商品数据采集任务
  • 微服务熔断降级方案对比:Hystrix、Resilience4j与Sentinel实践
  • 解决在windows中基于Spring AI 集成文件管理MCP服务遇到的问题
  • 【研究生随笔】PyTorch中的概率论
  • 青少年活动中心网站建设依据青岛标志设计公司