Collection与数据结构 顺序表与ArrayList

1. 线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
在这里插入图片描述

2. 顺序表

顺序表是一段物理空间连续的线性表,在底层一般使用数组来实现,在数组的基础上完成增删查改.下面是顺序表的一些接口.

2.1 接口

public interface Ilist {void add(int data);//为顺序表的尾部增加元素void add(int data ,int pos);//为指定位置添加元素void display();//打印顺序表int size ();//检测顺序表中元素的个数boolean contains(int toFind);//检测顺序表中是否包含该元素int indexOf(int toFind);//返回所要寻找第一个元素的下标int get(int index);//获取指定下标的元素void set(int index,int val);//把指定下标的元素指定为指定元素void remove(int toRomve);//移除第一个指定的元素void clear();//清空顺序表
}

下面我们来实现这些接口:

import java.util.Arrays;/*** 顺序表底层是用数组来实现的*/
public class MyArrayList implements Ilist {private int[] elem;private int size;//记录有效数据public static final int DEFAULT_CAPACITY = 5;//默认容量private boolean isFull(){return size == elem.length;//判断顺序表的容量是否为满}private void checkPos(int pos){if (pos < 0 || pos >= size){throw new PosException("pos is false");//判断插入位置是否合法}}private boolean isEmpty(){return this.size == 0;}public MyArrayList() {this.elem = new int[DEFAULT_CAPACITY];//默认容量为5this.size = 0;}//无参数的构造方法public void add(int data){//在末尾的位置添加元素if (isFull()){elem = Arrays.copyOf(elem,elem.length*2);//扩容}elem [size] = data;size++;}public void add(int data ,int pos){//在指定位置添加元素checkPos(pos);if (isFull()){elem = Arrays.copyOf(elem,elem.length*2);//扩容}for (int i = size-1; i >= pos ; i--) {//数组整体后移elem [i+1] = elem [i];}elem[pos] = data;size++;}public void display(){//打印顺序表System.out.print("["+" ");for (int i = 0; i < size; i++) {//打印有效元素System.out.print(elem[i]+" ");}System.out.print("]");}public int size (){//返回当前顺序表大小return this.size;}public boolean contains(int toFind){for (int i = 0; i < size; i++) {//在这里不可以用elem.length,后面的扩容之后未赋值if(elem[i] == toFind){return true;}}return false;}public int indexOf(int toFind){//返回要找的元素第一个返回的下标for (int i = 0; i < size; i++) {//在这里不可以用elem.length,后面的扩容之后未赋值if(elem[i] == toFind){return i;}}return -1;}public int get(int index){//获取index位置的值checkPos(index);if (isEmpty()){//存在默认容量5,若没有此方法,可能会在未初始化的位置上直接获取元素,获取成功//但是为0,不符合实际throw new EmptyException("array is empty");}return elem[index];}public void set(int index,int val){//把index位置的值改为valcheckPos(index);if (isEmpty()){//存在默认容量5,若没有此方法,可能会在未初始化的位置上直接添加元素,//添加成功,但是不符合实际throw new EmptyException("array is empty");}elem[index] = val;}public void remove(int toRomve){//移除第一次出现的元素if (isEmpty()){throw new EmptyException("array is empty");}int index = indexOf(toRomve);//先找到下标的位置for (int i = index+1; i < size; i++) {elem[i-1] = elem[i];}elem[size-1] = 0;size --;}public void clear(){size = 0;}
}public class EmptyException extends NullPointerException{public EmptyException(String s) {super(s);}
}public class PosException extends ArrayIndexOutOfBoundsException{public PosException(String s) {super(s);}
}

下面通过一些测试用例;来测试:

public class Main {public static void main(String[] args) {MyArrayList list = new MyArrayList();list.add(0);list.add(1);list.add(3);list.add(4);list.add(2,2);list.add(5);list.display();System.out.println(list.size());list.remove(2);list.display();System.out.println(list.size());}
}

在这里插入图片描述

3.ArrayList简介

在这里插入图片描述
[说明]

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

4.ArrayList的使用

4.1 ArrayList的构造方法

方法解释
public ArrayList()无参构造方法
public ArrayList(int initialCapacity)指定顺序表初始容量
public ArrayList(Collection<? extends E> c)利用Collection中的容器来构造

关于第三个构造方法,不太好理解,我们下面来解释一下:ArrayList已经传入了泛型的参数,就是E,这里用来构造ArrayList的Collection类中的元素必须是E的子类.

ArrayList<Integer> list = new ArrayList<>();
ArrayList<Integer> list1 = new ArrayList<>(list);
ArrayList<Number> list2 = new ArrayList<>(list);
ArrayList<Integer> list3 = new ArrayList<>(10);

4.2 ArrayList常见操作

方法解释
boolean add(E e)在尾部添加元素
void add(int index,E element)在指定位置添加元素
boolean addAll(Collection<? extends E> c)把c中的元素全部添加到顺序表尾部
E remove(int index)移除指定位置的元素
boolean remove(Object o)移除遇到的第一个元素o
E get(int index)获取指定位置的元素
E set(int index,E element)把指定位置的元素设置为指定的值
void clear()清空顺序表
boolean contains(Object o)检测顺序表中是否包含o
int indexOf(Object o)返回第一个指定元素所在的下标
int lastIndexOf(Object o)从后向前找,返回第一个元素所在的下标
List subList(int fromIndex,int toIndex)截取指定范围的字符串,左闭右开

在这里说明一下两个remove方法的区别,避免混淆,第一个remove方法时移除指定位置的元素,传入的元素类型为int类型的数据,而第二个remove方法移除的是第一个遇到的元素,这里传入的参数类型是和顺序表泛型相同的类型,当一个顺序表中存储的是Integer类型的数据的时候,要注意区分下标和元素.
下面对上述方法进行演示:

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有四种遍历方式,一种是通过sout直接输出,一种是for-i,一种是for-each,一种是使用迭代器.

import java.util.ArrayList;
import java.util.Iterator;
public class TestArrayList {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);//通过sout去遍历ArrayListSystem.out.println(list);//通过fori遍历for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i)+" ");}System.out.println();//通过foreach遍历for (int x:list) {System.out.print(x+" ");}System.out.println();//通过迭代器遍历Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()){System.out.print(iterator.next()+" ");}System.out.println();}
}

4.4 ArrayList扩容机制

ArrayList是动态的顺序表,在顺序表的容量不够的时候会自动扩容,下面是底层代码对ArrayList的扩容机制.

	public boolean add(E e) {modCount++;//底层是C/C++代码add(e, elementData, size);//调用另一个重载的add方法,指定添加容积return true;}private void add(E e, Object[] elementData, int s) {if (s == elementData.length)//容器满的时候需要扩容elementData = grow();//调用grow方法扩容elementData[s] = e;size = s + 1;}private Object[] grow() {return grow(size + 1);//最小容积是size+1,就是指定的添加容积+1}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 static int newLength(int oldLength, int minGrowth, int prefGrowth) {// preconditions not checked because of inlining// assert oldLength >= 0// assert minGrowth > 0int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow//若pre大,1.5被扩容,若是min大,直接加上指定的最小容积if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {return prefLength;} else {// put code cold in a separate methodreturn hugeLength(oldLength, minGrowth);}}

[总结]

  1. 预估要扩容的大小
  • 初步预估按照1.5倍扩容.
  • 如果用户所需大小预估超过1.5,则按照用户所需大小扩容.
  1. 使用copyOf扩容.

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

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

相关文章

【Docker】搭建强大的Nginx可视化配置工具 - nginxWebUI

【Docker】搭建强大的Nginx可视化配置工具 - nginxWebUI 前言 本教程基于绿联的NAS设备DX4600 Pro的docker功能进行搭建。 简介 NginxWebUI是一个基于Java的&#xff0c;专门用来管理Nginx的图形界面工具。它是开源的&#xff0c;使用相对简单且功能全面。 使用NginxWebUI…

接劳巴,拔掉KL15,MCU重启。不接劳巴,拔掉KL15,MCU正常下电

最近遇到一个神奇的现象&#xff0c;在调试一个单KL15的项目&#xff0c;发现接着劳特巴赫调试器&#xff0c;然后拔掉KL15&#xff0c;软件进入了重启Reset函数&#xff0c;没有进入期望的下电SwitchOff函数。 而不接劳特巴赫&#xff0c;拔掉KL15&#xff0c;观测电流&#…

Qt实现Kermit协议

1 概述 Kermit文件运输协议提供了一条从大型计算机下载文件到微机的途径。它已被用于进行公用数据传输。 其特性如下: Kermit文件运输协议是一个半双工的通信协议。它支持7位ASCII字符。数据以可多达96字节长度的可变长度的分组形式传输。对每个被传送分组需要一个确认。Kerm…

python-判断列表字典循环

比较运算符 不等于 &#xff01; if 布尔值&#xff1a; [执行语句-真实执行] else: [执行语句] mood_index int(input("对象今天的心情指数的是&#xff1a;")) if mood_index > 60:print("恭喜&#xff0c;今晚应该可以带游戏&#xff0c;去吧")…

2024年水电站大坝安全监测工作提升要点

根据《水电站大坝运行安全监督管理规定》&#xff08;国家发改委令第23号&#xff09;和《水电站大坝运行安全信息报送办法》&#xff08;国能安全〔2016〕261号&#xff09;的相关规定、要求&#xff0c;电力企业应当在汛期向我中心报送每日大坝汛情。近期&#xff0c;全国各地…

【机器学习】深度解析KNN算法

深度解析KNN算法 KNN&#xff08;K-最近邻&#xff09;算法是机器学习中一种基本且广泛应用的算法&#xff0c;它的实现简单直观&#xff0c;应用范围广泛&#xff0c;从图像识别到推荐系统都有其身影。然而&#xff0c;随着数据量的增长&#xff0c;KNN算法面临着严峻的效率挑…

[yolox]ubuntu上部署yolox的ncnn模型

首先转换pytorch->onnx->param模型&#xff0c;这个过程可以查资料步骤有点多&#xff0c;参考blog.51cto.com/u_15660370/6408303&#xff0c;这里重点讲解转换后部署。 测试环境&#xff1a; ubuntu18.04 opencv3.4.4(编译过程省略&#xff0c;参考我其他博客) 安装…

【智能家居入门3】(MQTT服务器、MQTT协议、微信小程序、STM32)

前面已经写了三篇博客关于智能家居的&#xff0c;服务器全都是使用ONENET中国移动&#xff0c;他最大的优点就是作为数据收发的中转站是免费的。本篇使用专门适配MQTT协议的MQTT服务器&#xff0c;有公用的&#xff0c;也可以自己搭建&#xff08;应该要钱&#xff09;&#xf…

常见的数学方法

Math类表示数学类&#xff0c;其中的数学方法都被定义成为static形式&#xff0c;所以可以直接通过Math类的类名调用某个数学方法。语法格式&#xff1a; Math.xxx(参数)&#xff1b; 例题 输入n个整数a1,a2,a3,......an,求这n个数的最大值max&#xff0c;最小值min&#xff0…

算法之并查集

并查集&#xff08;Union-find Data Structure&#xff09;是一种树型的数据结构。它的特点是由子结点找到父亲结点&#xff0c;用于处理一些不交集&#xff08;Disjoint Sets&#xff09;的合并及查询问题。 Find&#xff1a;确定元素属于哪一个子集。它可以被用来确定两个元…

【御控物联】 IOT异构数据JSON转化(场景案例一)

文章目录 前言技术资料 前言 随着物联网、大数据、智能制造技术的不断发展&#xff0c;越来越多的企业正在进行工厂的智能化转型升级。转型升级第一步往往是设备的智能化改造&#xff0c;助力设备数据快速上云&#xff0c;实现设备数据共享和场景互联。然而&#xff0c;在生产…

【蓝桥杯】填空题技巧|巧用编译器|用Python处理大数和字符|心算手数|思维题

目录 一、填空题 1.巧用编译器 2.巧用Excel 3. 用Python处理大数 4.用Python处理字符 5.心算手数 二、思维题 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击跳转到网站】 一、填空题 …

蓝桥杯day14刷题日记

P8707 [蓝桥杯 2020 省 AB1] 走方格 思路&#xff1a;很典型的动态规划问题&#xff0c;对于偶数格特判&#xff0c;其他的正常遍历一遍&#xff0c;现在所处的格子的方案数等于左边的格子的方案数加上上面格子的方案数之和 #include <iostream> using namespace std; …

蓝桥杯物联网竞赛_STM32L071_13_定时器

CubeMx配置LPTIM: counts internal clock events 计数内部时钟事件 prescaler 预分频器 updata end of period 更新期末 kil5配置&#xff1a; 中断回调函数完善一下&#xff1a; void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim){if(cnt ! 10) cnt…

iOS - Runloop介绍

文章目录 iOS - Runloop介绍1. 简介1.1 顾名思义1.2. 应用范畴1.3. 如果没有runloop1.4. 如果有了runloop 2. Runloop对象3. Runloop与线程4. 获取Runloop对象4.1 Foundation4.2 Core Foundation4.3 示例 5. Runloop相关的类5.1 Core Foundation中关于RunLoop的5个类5.2 CFRunL…

152 Linux C++ 通讯架构实战7 ,makefile编写改成for cpp,读配置文件,内存泄漏查找,设置标题实战

读写配置文件代码实战。nginx.conf 一个项目要启动&#xff0c;需要配置很多信息&#xff0c;第一项就是学习如何配置一个项目 nginx.conf的内容 #是注释行&#xff0c; #每个有效配置项用 等号 处理&#xff0c;等号前不超过40个字符&#xff0c;等号后不超过400个字符&#…

SpringBoot分布式锁自定义注解处理幂等性

SpringBoot分布式锁自定义注解处理幂等性 注解简介 注解&#xff08;Annotation&#xff09;是Java SE 5.0 版本开始引入的概念&#xff0c;它是对 Java 源代码的说明&#xff0c;是一种元数据&#xff08;描述数据的数据&#xff09;。 Java中的注解主要分为以下三类: JDK…

【QT+QGIS跨平台编译】043:【protoc+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、protoc介绍二、文件下载三、文件分析四、pro文件五、编译实践一、protoc介绍 protoc 是 Protocol Buffers 的官方编译器 可执行文件版本。与在 Linux 或 macOS 等系统上的 protoc 类似,protoc.exe 在 Windows 环境下提供了相同的功能,用于将 .…

下拉选中搜索angularjs-dropdown-multiselect.js

需要引入angularjs-dropdown-multiselect.js 页面 <div ng-dropdown-multiselect"" options"supplierList_data" selected-model"supplierList_select" events"changSelValue_supplierList" extra-settings"mucommonsetti…

【MySQL】7.MHA高可用配置及故障切换

什么是MHA MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件 mha用于解决mysql的单点故障问题&#xff1b; 出现故障时&#xff0c;mha能在0~30秒内自动完成故障切换&#xff1b; 并且能在故障切换过程中&#xff0…