【Java 数据结构】List,ArrayList与顺序表

目录

一. List

1.1 什么是List

1.2 List 的常见方法

1.3 List 的使用

二. 顺序表

2.1 什么是顺序表

2.2 实现自己的顺序表

2.2.1 接口实现

2.2.2 实现顺序表

三. ArrayList

3.1 ArrayList简介

3.2 ArrayList的三个构造方法

3.2.1 无参构造方法

3.2.2 带一个参数的构造方法

3.3 ArrayList的常见方法

3.4 ArrayList 的遍历

3.4.1 直接打印

3.4.2 for循环遍历

3.4.3 借助for-each遍历

3.4.4 迭代器遍历


一. List

1.1 什么是List

在集合框架中,List是一个接口,继承自Collect

站在数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删改查以及变量等操作

1.2 List 的常见方法

下面是List接口中的一些常见方法

1.3 List 的使用

由于List 是一个接口,不能直接实例化对象,但是在集合框架中,ArrayList和LinkedList都实现了List接口


二. 顺序表

2.1 什么是顺序表

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般采用数组存储,ArrayList就是顺序表的一种实现形式

2.2 实现自己的顺序表

在学习ArrayList之前,我们可以先试着写一个自己实现的顺序表,能帮助我们在使用ArrayList的方法以及了解它时更加得心应手

2.2.1 接口实现

public class IList {public void add(int data) { }// 在 pos 位置新增元素public void add(int pos, int data) { }// 判定是否包含某个元素public boolean contains(int toFind) { return true; }// 查找某个元素对应的位置public int indexOf(int toFind) { return -1; }// 获取 pos 位置的元素public int get(int pos) { return -1; }// 给 pos 位置的元素设为 valuepublic void set(int pos, int value) { }//删除第⼀次出现的关键字keypublic void remove(int toRemove) { }// 获取顺序表⻓度public int size() { return 0; }// 清空顺序表public void clear() { }// 打印顺序表,注意:该⽅法并不是顺序表中的⽅法,为了⽅便看测试结果给出的public void display() { }
}

下面,我们自己的顺序表将会实现并重写IList中的所有方法

2.2.2 实现顺序表

import java.util.Arrays;class EmptyListException extends RuntimeException{public EmptyListException(String message) {super(message);}
}class IndexException extends RuntimeException{public IndexException(String message) {super(message);}
}
public class MyArrayList implements IList{public int arr[];public final int Initial_Capacity=10;public int Used_size;public MyArrayList() {this.arr = new int [Initial_Capacity];}@Overridepublic void add(int data) {if(is_full()){grow();}this.arr[Used_size]=data;Used_size++;}@Overridepublic void add(int pos, int data) {if(is_full()){grow();}checkPos(pos);for (int i =Used_size-1; i>=pos; i--) {arr[i+1]=arr[i];}arr[pos]=data;Used_size++;}public boolean is_full(){if(arr.length==Used_size){return true;}return false;}public void grow(){this.arr= Arrays.copyOf(arr,arr.length*2);}@Overridepublic boolean contains(int toFind) {for (int i = 0; i <arr.length; i++) {if(arr[i]==toFind){return true;}}return false;}@Overridepublic int indexOf(int toFind) {for (int i = 0; i <arr.length; i++) {if (arr[i] == toFind) {return i;}}return -1;}@Overridepublic int get(int pos) {check(pos);isEmpty();return arr[pos];}public void check(int pos){if(pos<0||pos>=Used_size){throw new IndexException(pos+"位置下标访问不合法");}}public void checkPos(int pos){if(pos<0||pos>Used_size){throw new IndexException(pos+"位置下标访问不合法");}}public void isEmpty(){if(Used_size==0){throw new EmptyListException("该表为空表");}}@Overridepublic void set(int pos, int value) {check(pos);arr[pos]= value;}@Overridepublic void remove(int toRemove) {int index=indexOf(toRemove);if(index==-1){System.out.println("没有要删除的元素");return;}for (int i =index; i <Used_size-1; i++) {arr[i]=arr[i+1];}Used_size--;}@Overridepublic int size() {return Used_size;}@Overridepublic void clear() {for (int i = 0; i <Used_size; i++) {arr[i]=0;}Used_size=0;//如果数组中的是引用数据类型的元素时,一定要将其全部置为null(避免空间造成浪费)}@Overridepublic void display() {for (int i = 0; i <this.Used_size; i++) {System.out.print(arr[i]+" ");}System.out.println();}
}

注意:

  • 在删除和特定位置添加元素的方法中采用的是覆盖的思想,下面是添加元素到特定位置的流程图(将6添加到3下标位置)

  • 在 clear()中如果要清空的顺序表是存放引用数据类型的话,一定要将其全部设置为null

三. ArrayList

3.1 ArrayList简介

在集合框架中,ArrayList是一个普通的类,实现了List接口。具体框架如下:

注意:

  • ArrayList是以泛型的形式实现的,使用时必须要先实例化
  • ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

3.2 ArrayList的三个构造方法

3.2.1 无参构造方法

下面是ArrayList类中的源码截取:

 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}private Object[] grow(int minCapacity) {int oldCapacity = elementData.length;if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {int newCapacity = ArraysSupport.newLength(oldCapacity,minCapacity - oldCapacity, /* minimum growth */oldCapacity >> 1           /* preferred growth */);return elementData = Arrays.copyOf(elementData, newCapacity);} else {return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];}}public void add(int index, E element) {rangeCheckForAdd(index);modCount++;final int s;Object[] elementData;if ((s = size) == (elementData = this.elementData).length)elementData = grow();System.arraycopy(elementData, index,elementData, index + 1,s - index);elementData[index] = element;size = s + 1;}

解释:

这里的 elementData 是 ArrayList 内部用于存储元素的数组,DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是一个空数组。当使用无参构造方法创建 ArrayList 时,实际上只是将 elementData 初始化为一个空数组。当向 ArrayList 中添加第一个元素(仅限添加的第一个元素)时, ArrayList 会自动扩容,将数组容量扩展为默认容量(通常是10)。

3.2.2 带一个参数的构造方法

  • ArrayList(int initialCapacity)
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);}}

解释:通过这个构造方法,当传入一个大于0的整数作为参数时, ArrayList 会创建一个具有指定容量的数组来存储元素,这样可以在已知元素大概数量的情况下,减少数组扩容的次数,提高性能。如果传入0,则使用一个空数组。如果传入负数,会抛出异常,因为容量不能为负

  • ArrayList(Collection<? extends E> c)
 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;}}

解释:使用集合类来构造ArrayList,将该集合类中的所有元素用来构造ArrayList,和ArrayList中的 addAll(Collection<? extends E> c)的作用类似,其中Collection<? extends E> c 表示可以传入实现了Collection接口并且泛型参数类型是E/E子类的集合类,下面是一个例子:这里不是一个集合类一个元素(与List的嵌套不同)

public static void main(String[] args) {ArrayList<Integer> list0=new ArrayList<>();list0.add(1);list0.add(2);ArrayList<Integer> list1=new ArrayList<>();list1.add(1);list1.add(2);ArrayList<Integer> list=new ArrayList<>(list0);//使用List0这个集合类来构造listlist.add(100);//向list中添加元素list.addAll(list1); //向list中来添加集合类System.out.println(list);System.out.println(list.size());}打印结果:
[1, 2, 100, 1, 2]
5
public static void main(String[] args) {ArrayList<ArrayList<Integer>> lists=new ArrayList<>();ArrayList<Integer> list3=new ArrayList<>();list3.add(1);list3.add(2);list3.add(3);lists.add(list3);System.out.println(lists.size());}打印结果:1

3.3 ArrayList的常见方法

ArrayList的方法很多,以下只列举常见的几种:

注意:

  • LIst<E>subList(int formIndex,int toIndex) 这个方法要重点注意(是个坑),1. 这个方法的返回值实际上是截取list部分的首地址,如果改变subList中的元素,被截取的原list中的元素也会发生改变,2. 截取部分是[  )

3.4 ArrayList 的遍历

3.4.1 直接打印

 public static void main(String[] args) {ArrayList<Integer> list3=new ArrayList<>();list3.add(1);list3.add(2);list3.add(3);System.out.println(list3);}打印结果:[1,2,3]

3.4.2 for循环遍历

public static void main(String[] args) {ArrayList<Integer> list3=new ArrayList<>();for (int i = 0; i <list3.size(); i++) {System.out.print(list3.get(i)+" ");}System.out.println();}打印结果:1 2 3

3.4.3 借助for-each遍历

public static void main(String[] args) {ArrayList<Integer> list3=new ArrayList<>();list3.add(1);list3.add(2);list3.add(3);for(Integer integer: list3){System.out.print(integer+" ");}}打印结果:1 2 3

3.4.4 迭代器遍历

 public static void main(String[] args) {ArrayList<Integer> list3=new ArrayList<>();list3.add(1);list3.add(2);list3.add(3);Iterator<Integer> it=list3.iterator();while(it.hasNext()){System.out.print(it.next()+" ");}System.out.println();ListIterator<Integer> it2=list3.listIterator(list3.size());while(it2.hasPrevious()){  //倒着打印System.out.print(it2.previous()+" ");}System.out.println();ListIterator<Integer> it3=list3.listIterator(1);while(it3.hasNext()){   //从指定位置打印System.out.print(it3.next()+" ");}}打印结果:
1 2 3 
3 2 1 
2 3

注意:

  • 原理:Arraylist中重写了literable接口中iterator()方法(),该方法的返回值是一个实现了Iterator接口的类Itr(Itr类是一个定义在ArrayList类内部的的一个私有内部类)的实例化对象(Iterator接口没有继承任何接口),通过这个对象可以调用Iterator接口的各种方法进行遍历
  • ListIterator接口 实际上扩展了 Iterator接口,新增hasPrevious()和Previous()等方法,且在调用ListIterator()可传入参数,从特定位置进行打印,使得打印更加灵活
  • ArrayList的扩容机制是扩1.5倍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

18.第二阶段x64游戏实战-MFC列表框

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;17.第二阶段x64游戏实战-人工遍历二叉树结构 现在找到了附近npc列表&#xff0…

如何解决 Xcode 签名证书和 Provisioning Profile 过期问题

在 iOS 应用开发过程中&#xff0c;签名证书和 Provisioning Profile 是确保应用安全性和合法性的关键组件。然而&#xff0c;当这些证书或配置文件过期时&#xff0c;开发者可能会遇到编译或归档失败的问题。本文将详细介绍如何解决 Xcode 中“iOS Distribution”证书未找到和…

SpringBoot Actuator未授权访问漏洞的全面解析与解决方案

引言 SpringBoot Actuator 作为应用监控与管理的核心组件,为开发者提供了丰富的系统自省和运维能力。然而,其默认配置中可能存在的未授权访问漏洞,已成为企业安全防护的潜在风险。本文将从漏洞原理、影响范围、检测方法到解决方案,系统性地剖析该问题,并提供覆盖开发、运维…

gin框架学习笔记

Gin 是一个基于 Go 语言的高性能 Web 框架 gin下载 在已有的go项目直接终端输入 go get -u github.com/gin-gonic/gin hello world快速上手 package mainimport ("github.com/gin-gonic/gin" )func main() {router : gin.Default()router.GET("/", func…

linux中由于编译选项-D_OS64BIT导致的核心已转储问题

linux中由于编译选项-D_OS64BIT导致的核心已转储问题排查解决&#xff1a; 原因&#xff1a; a.so b.so a.so使用b.so 程序1 程序2 使用a.so 程序1运行正常&#xff0c;程序2启动后提示核心已转储。 程序1和程序2运行的代码都一致&#xff0c;只执行创建xApplication app&…

什么是ICSP编程

ICSP编程介绍 ICSP 编程&#xff08;In-Circuit Serial Programming&#xff09;&#xff0c;即“在线串行编程”&#xff0c;是一种通过 SPI 协议 直接对微控制器&#xff08;如 Arduino 的 ATmega328P&#xff09;进行编程的技术&#xff0c;无需移除芯片。它常用于以下场景…

基于Vue3和OpenLayers的WebGIS示例程序

笔记参考教程来源于B站UP主znlgis的视频合集&#xff1a;https://space.bilibili.com/161342702&#xff0c;直播使用的源码地址&#xff1a;https://github.com/OpenGisToolbox。 Demo合集分为5大部分&#xff0c;分别是&#xff1a;基础环境搭建、项目搭建、GeoServer Rest A…

UBUS 通信接口的使用——添加一个object对象(ubus call)

1&#xff0c;引入 ubus提供了一种多进程通信的机制。存在一个守护进程ubusd&#xff0c;所以进程都注册到ubusd&#xff0c;ubusd进行消息的接收、分发管理。 ubus对多线程支持的不好&#xff0c;例如在多个线程中去请求同一个服务&#xff0c;就有可能出现不可预知的结果。 …

【Python魔法方法(特殊方法)】

在 Python 中&#xff0c;许多运算符都可以进行重载&#xff0c;以下是一些常见运算符及其对应的魔法方法&#xff08;特殊方法&#xff09;&#xff1a; 算术运算符 加法 &#xff1a;__add__ 用于定义对象相加的行为。例如&#xff0c;当你对两个自定义类的实例使用 运算符…

(三十二)Android开发中AppCompatActivity和Activity之间的详细区别

在 Android 开发中&#xff0c;AppCompatActivity 和 Activity 是两个核心类&#xff0c;用于创建和管理应用程序的用户界面。尽管它们功能上有重叠&#xff0c;但它们之间存在显著的区别。本文将详细讲解 AppCompatActivity 和 Activity 的区别&#xff0c;并结合代码示例和具…

【 C++核心知识点面试准备:从内存管理到STL与模板 】

一、动态内存管理&#xff1a;new/delete与底层原理 核心问题1&#xff1a;new/delete vs malloc/free 区别对比&#xff1a; 特性new/deletemalloc/free类型安全自动推导类型&#xff0c;无需转型返回void*&#xff0c;需强制转型生命周期自动调用构造/析构函数需手动初始化…

软考高项(信息系统项目管理师)第 4 版全章节核心考点解析(第4版课程精华版)

一、核心输入输出速记体系&#xff08;力扬老师独家口诀&#xff09; &#xff08;一&#xff09;规划阶段万能输入&#xff08;4 要素&#xff09; 口诀&#xff1a;章程计划&#xff0c;组织事业 ✅ 精准对应&#xff08;ITTO 核心输入&#xff09;&#xff1a; 章程&#…

ASP.NET CORE部署IIS的三种方式

ASP.NET Core 部署方式对比 本文档对比了三种常见的 ASP.NET Core 应用&#xff08;如你的 DingTalkApproval 项目&#xff09;部署到 Windows 10 上 IIS 服务器的方式&#xff1a;dotnet publish&#xff08;手动部署&#xff09;、Web Deploy&#xff08;直接发布到 IIS&…

基于共享上下文和自主协作的 RD Agent 生态系统

在llmangentmcp这个框架中&#xff1a; LLM&#xff1a; 依然是智能体的“大脑”&#xff0c;赋予它们理解、推理、生成和规划的能力&#xff0c;并且也用于处理和利用共享上下文。Agent&#xff1a; 具备特定 R&D 职能的自主单元&#xff0c;它们感知共享上下文&#xff0…

zephyr架构下Bluetooth advertising接口

目录 概述 1 函数接口 2 主要函数介绍 2.1 bt_le_adv_start函数 2.1.1 函数功能介绍 2.1.2 典型使用示例 2.1.3 广播间隔 2.1.4 注意事项 2.2 bt_le_adv_stop 函数 2.2.1 函数功能 2.2.2 使用方法介绍 2.2.3 实际应用示例 2.2.4 关键注意事项 2.2.5 常见问题解决 …

8、HTTPD服务--ab压力测试

一、ab压力测试 # ab ‐c 100 ‐n 1000 http://vedio.linux.com/index.html 2 This is ApacheBench, Version 2.3 <$Revision: 1430300 $> 3 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 4 Licensed to The Apache Software Foundation,…

E2E 测试

以下是关于端到端(E2E)测试的基本知识总结: 一、E2E 测试核心认知 1. 定义与价值定位 "模拟真实用户在完整应用环境中的操作流程"核心价值: 验证跨系统/模块的集成功能检测用户流程中的关键路径保障核心业务场景的可用性测试金字塔定位:单元测试(70%) → 集…

python之数字类型的操作

Python数据类型与操作符完全指南&#xff1a;详解各类数据操作技巧 目录 数字类型 字符串 列表 元组 字典 集合 布尔 通用操作符 注意事项 1. 数字类型&#xff08;int, float, complex&#xff09; 数字类型是Python中最基础的数据类型&#xff0c;支持多种数学运算…

基于Spring Boot+Vue 网上书城管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

从拒绝采样到强化学习,大语言模型推理极简新路径!

大语言模型&#xff08;LLMs&#xff09;的推理能力是当下研究热点&#xff0c;强化学习在其复杂推理任务微调中广泛应用。这篇论文深入剖析了相关算法&#xff0c;发现简单的拒绝采样基线方法表现惊人&#xff0c;还提出了新算法。快来一探究竟&#xff0c;看看这些发现如何颠…