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

【数据结构】顺序表,ArrayList

文章目录

  • 前言
  • ArrayList简介
  • ArrayList使用
    • 构造方法
    • ArrayList常见操作
      • remove
      • subList
    • 遍历ArrayList
    • ArrayList中的二维数组
  • 总结


前言

在上一篇博文中,我们尝试自己实现了一下ArrayList类。不过,在实际应用中,ArrayList有着更灵活、更便捷的使用方法。在这一篇博文中,让我们更加深入的了解一下吧。


ArrayList简介

在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:
在这里插入图片描述
【说明】

  1. ArrayList是以泛型方式实现的,使用时必须要先实例化

  2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问

  3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的

  4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的

  5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList

  6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

ArrayList使用

构造方法

public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}/*** Constructs an empty list with an initial capacity of ten.*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/*** Constructs a list containing the elements of the specified* collection, in the order they are returned by the collection's* iterator.** @param c the collection whose elements are to be placed into this list* @throws NullPointerException if the specified collection is null*/public ArrayList(Collection<? extends E> c) {Object[] a = c.toArray();if ((size = a.length) != 0) {if (c.getClass() == ArrayList.class) {elementData = a;} else {elementData = Arrays.copyOf(a, size, Object[].class);}} else {// replace with empty array.elementData = EMPTY_ELEMENTDATA;}}

我们如果去看源码,会发现ArratList有三个构造方法。首先第一个不必多说,第二个其实是创建一个空表,详情请看下图:
在这里插入图片描述

我们主要来讲第三个:

public ArrayList(Collection<? extends E> c) {

首先Collection是这些表类的父类,“?”指的是通配符,参数的意思是:给参数时要保证首先类型是Collection或者它的子类,<>里面的得是E的子类。举例说明一下大家就很快明白了。

import java.util.ArrayList;//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);System.out.println(list);ArrayList<Integer> list1 = new ArrayList<>(list);System.out.println(list1);}}

在这里插入图片描述
首先List< Integer>肯定是Collection类的子类,而Integer与ArrayList list1 = new ArrayList<>(list);所代表的Integer包装类又是相同的,所以,可以这样定义一个新表。

但是!!!!!!!!!!!!!!!!!!到这里构造方法还没完。
上一个博文中我们实现add方法时会扩容。此时,在第一个和第二个构造方法中,我们可能会建立空表,如果是空表,照我们的代码来看,似乎没办法扩容以及插入数据啊?我们来看java具体是怎么实现的吧!

在这里插入图片描述
在这里插入图片描述
我们可以看到,其实是java先给原来的size + 1之后,才进行的扩容操作,并且扩容是按照1.5倍进行扩容的。

ArrayList常见操作

ArrayList虽然提供的方法比较多,但是常用方法如下所示

在这里插入图片描述
这些方法我们大多数都实现了,这里讲两个没提到的。

remove

我们能注意到,remove既可以传数据,又可以传下标。那么问题来了:我们传入一个“1”,那我指的是下标还是数据呢?

import java.util.ArrayList;//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);System.out.println(list);
//        ArrayList<Integer> list1 = new ArrayList<>(list);
//        System.out.println(list1);list.remove(1);System.out.println(list);}}

在这里插入图片描述
是下标!
那怎么才能传数据呢?

list.remove(new Integer(1));System.out.println(list);

在这里插入图片描述
但是自从java9以来,这种写法变得过时了,编译器会报错。
在这里插入图片描述

subList

subList在截取过程中有一个有意思的现象:

import java.util.ArrayList;
import java.util.List;//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);System.out.println(list);List<Integer> list1 = list.subList(1,3);list1.set(1,999);System.out.println(list);System.out.println(list1);}}

在这里插入图片描述
可以看到我们修改list1的内容时,list的内容也改变了,这是因为subList不是建立一个新对象,而是建立一个新索引,仍然指向原表。

遍历ArrayList

我们有四种方法来遍历ArrayList,其中有两种为使用迭代器遍历,这是一个新增的知识:

public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);System.out.println("for下标遍历");for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i) + " ");}System.out.println();System.out.println("foreach遍历");for (Integer x : list){System.out.print(x + " ");}System.out.println();System.out.println("使用迭代器Iterator输出");Iterator<Integer> it = list.iterator();while(it.hasNext()){System.out.print(it.next() + " ");}System.out.println();System.out.println("使用迭代器ListIterator输出");ListIterator<Integer> it2 = list.listIterator();while(it2.hasNext()){System.out.print(it2.next() + " ");}System.out.println();System.out.println("使用迭代器ListIterator输出====扩展(反向输出)");ListIterator<Integer> it3 = list.listIterator(list.size());while(it3.hasPrevious()){System.out.print(it3.previous() + " ");}System.out.println();}

在这里插入图片描述

注意

  1. ArrayList最长使用的遍历方式是:for循环+下标 以及 foreach
  2. 迭代器是设计模式的一种,后序容器接触多了再给大家铺垫

ArrayList中的二维数组

在这里插入图片描述
大家来看一道简单的杨辉三角的题目,看上去似乎很简单,但是请看这里:

public List<List<Integer>> generate(int numRows) {

List<List< Integer >>这啥玩意儿?????

在这之前确实没见过这种写法,但我们可以拆开理解一下。
先看里面:
List< Integer>
这个都认识,数据类型为Integer的List表。

那这个List<List< Integer>>是不是就是类型为List< Integer>的List表了呢?
或者我来这样说,这是不是就是一个二维数组呢??
没错,这样的写法代表的就是List的一个类似于二维数组的表示,即:List表中的每一个数据都是一个list表

这一题的代码也很简单:

 public static List<List<Integer>> generate(int numRows) {List<List<Integer>> ret = new ArrayList<>();List<Integer> list0 = new ArrayList<>();list0.add(1);ret.add(list0);//从第2行开始 进行求每个元素for (int i = 1; i < numRows; i++) {//处理第一个元素List<Integer> curRow = new ArrayList<>();curRow.add(1);//中间List<Integer> preRow = ret.get(i-1);for (int j = 1; j < i; j++) {int val1 = preRow.get(j);int val2 = preRow.get(j-1);curRow.add(val1+val2);}//尾巴curRow.add(1);ret.add(curRow);}return ret;}

总结

顺序表作为最基础的数据结构之一,是理解更复杂结构的基石。它通过连续的内存空间和索引机制,实现了高效的元素访问,但在插入删除操作上存在性能瓶颈。

掌握顺序表的设计思想,不仅能帮助我们更好地理解编程语言中的内置集合(如 Java 的 ArrayList),也能为后续学习链表、栈、队列等结构打下坚实基础。

在实际开发中,应根据具体场景选择合适的数据结构 —— 需要频繁访问时选顺序表,需要频繁插入删除时可考虑链表,平衡二者优缺点的结构(如跳表)则适用于更复杂的场景。


文章转载自:

http://E7Xo3cEw.dbnrL.cn
http://Ubk6eLXl.dbnrL.cn
http://i5bcheHa.dbnrL.cn
http://BLIUkMp2.dbnrL.cn
http://TUVS5qbz.dbnrL.cn
http://CDSowWUV.dbnrL.cn
http://8ZfBaqfU.dbnrL.cn
http://f7z5bRl7.dbnrL.cn
http://sfk6COgV.dbnrL.cn
http://D1PmZg3r.dbnrL.cn
http://C4r0gi9R.dbnrL.cn
http://83S5ZmpM.dbnrL.cn
http://b0bbMKne.dbnrL.cn
http://77dv1loa.dbnrL.cn
http://wABfpJ2y.dbnrL.cn
http://hcgOl6g0.dbnrL.cn
http://31IHZyAy.dbnrL.cn
http://aDF790t0.dbnrL.cn
http://sqiil7vs.dbnrL.cn
http://BsQ25GXC.dbnrL.cn
http://vQV1ob2d.dbnrL.cn
http://2VnO4ATl.dbnrL.cn
http://0QLKGaUk.dbnrL.cn
http://1lVJtn8v.dbnrL.cn
http://IbaakQ5c.dbnrL.cn
http://JFcsLEWM.dbnrL.cn
http://nzaJq5vl.dbnrL.cn
http://sY84GbjE.dbnrL.cn
http://cIekU1eO.dbnrL.cn
http://DBncMqJM.dbnrL.cn
http://www.dtcms.com/a/387570.html

相关文章:

  • 第十二章 Arm C1-Premium GIC CPU接口详解
  • 【数据结构---并查集】(并查集的原理,实现与应用)
  • 【数据结构-KMP算法(学习篇)】
  • Start application catch exception
  • 机器视觉在半导体封装检测中的应用
  • 雅菲奥朗SRE知识墙分享(九):『变更管理的定义与实践』
  • 51c视觉~3D~合集6
  • webRTC 的协议族
  • 线激光相机 眼在手上六轴机器人手眼标定 备忘记录
  • QML学习笔记(一)基本了解和工程配置
  • 大数据毕业设计选题推荐-基于大数据的牛油果数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
  • Hadoop单机模式下运行grep实例,output文件目录不存在
  • 【docker】清理中断构建后产生的镜像和缓存
  • Vue2项目集成打包分析工具webpack-bundle-analyzer
  • 【阶梯波发生器如何控制电压和周期】2022-12-9
  • Java 设计模式之桥接模式(Bridge Pattern)
  • Android 端启动 HTTP 服务:从基础实现到实战应用
  • 《2D横版平台跳跃游戏中角色二段跳失效与碰撞体穿透的耦合性Bug解析》
  • 基于本机知识库 + 豆包(火山引擎)+ MCP的落地方案
  • OpenCV 风格迁移、DNN模块 案例解析及实现
  • php实现火山引擎 【双向流式websocket-V3-支持复刻2.0/混音mix】开箱即用,可用于各种PHP框架。
  • 【lua】Windows环境下cffi-lua使用指南:编译、安装与测试
  • 我优化了昨天的C++/Lua插件系统:添加了插件沙箱、Lua 状态池
  • 【数据库】SQLite安装部署与使用指南
  • Android Kotlin 请求方法代码
  • 【easy_tools】一个跨平台裸机工具库,包含任务/堆栈/消息/定时器/日志等实现
  • ARM(11) - LM75
  • FPGA实现SRIO数据回环传输,基于Serial Rapidlo Gen2架构,提供6套工程源码和技术支持
  • 第十九章 Arm C1-Premium TRBE技术解析
  • HTB writeup