Java —— ArrayList与顺序表

目录

1. 线性表

2. 顺序表

接口的实现

3. ArrayList简介

3.1 ArrayList介绍

3.2 ArrayList的构造方法

4. ArrayList的扩容机制

5. ArrayList的常见操作

6. ArrayList的遍历

7. 例题

8. ArrayList的具体使用

8.1 简单的洗牌算法

8.2 杨辉三角

9. ArrayList的问题及思考


1. 线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

2. 顺序表

顺序表是用一段物理地址连续的存储单元一次存储数据的线性结构,一般采用数组存储。在数组上完成数据的增删查改。

接口的实现

public class MyArrayList {// 这个类所操作的全部都是数组, 是提供一些方法用于操作private int[] elem; // 数组private int usedSize;   // 记录有效的数据的个数private static final int DEFAULT_SIZE = 10;// 提供一个构造方法public MyArrayList() {this.elem = new int[DEFAULT_SIZE];  // 对 elem 进行初始化}// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");}System.out.println();}// 新增元素, 默认在数组最后新增public void add(int data) {// 检查当前顺序表是否已满if (isFull()) {// 如果满就要扩容this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);}this.elem[this.usedSize] = data;this.usedSize++;}public boolean isFull() {/*if(size() >= this.elem.length){return true;}return false;*/return size() >= this.elem.length;}// 获取顺序表长度public int size() {return this.usedSize;}
}


    // 在 pos 位置新增元素.// 如果pos下标不合法,那么就会抛出一个 PosWrongfulExceptionpublic void add(int pos, int data) throws PosWrongfulException {if (isFull()) {System.out.println("满了");this.elem =Arrays.copyOf(this.elem, 2 * this.elem.length);}if (pos < 0 || pos > this.usedSize) {System.out.println("pos位置不合法!");throw new PosWrongfulException("pos位置不合法");}//pos一定是合法的//1. 开始挪动数据for (int i = this.usedSize - 1; i >= pos; i--) {this.elem[i + 1] = this.elem[i];}//2.插入数据this.elem[pos] = data;//3. usedSize++this.usedSize++;}
// pos 位置不合法的异常
public class PosWrongfulException extends RuntimeException{public PosWrongfulException() {}public PosWrongfulException(String message) {super(message);}
}


    // 判定是否包含某个元素public boolean contains(int toFind) {for (int i = 0; i < this.size(); i++) {if (this.elem[i] == toFind) {return true;}}return false;}// 查找某个元素对应的位置public int indexOf(int toFind) {for (int i = 0; i < this.size(); i++) {if (this.elem[i] == toFind) {return i;}}return -1;}// 获取 pos 位置的元素public int get(int pos) {if (isEmpty()) {throw new EmptyException("当前顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new PosWrongfulException("get获取元素的时候,pos不合法异常!");}return this.elem[pos];}public boolean isEmpty() {return size() == 0;}// 给 pos 位置的元素 更新 为 valuepublic void set(int pos, int value) {if (isEmpty()) {throw new EmptyException("当前顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new PosWrongfulException("set获取元素的时候,pos不合法异常!");}this.elem[pos] = value;}
public class EmptyException extends RuntimeException{public EmptyException() {}public EmptyException(String message) {super(message);}
}

    //删除第一次出现的关键字keypublic void remove(int key) {if (isEmpty()) {throw new EmptyException("顺序表为空!");}int index = this.indexOf(key);if (index == -1) {System.out.println("没有这个数字");return;}for (int i = index; i < size() - 1; i++) {this.elem[i] = this.elem[i + 1];}this.usedSize--;}


    // 清空顺序表public void clear() {this.usedSize = 0;}

3. ArrayList简介

3.1 ArrayList介绍

ArrayList是Java里面的一个集合类,这是一个具体的实现类叫做ArrayList,那么它实际上实现了许多接口:

【说明】

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

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

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

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

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

上图中,我们可以看到,ArrayList类继承了一个抽象类AbstractList,然后实现类List接口,List接口又扩展了Collection接口,Collection接口又扩展了Iterable接口,那么不管怎么样呢最重要的还是List接口。

我们需要跟着源码来学习其集合类,所以看一下ArrayList的源码。

首先,Java的集合类一般都在java.util包里面,这里可以通过编译器看到:

当我们点进查看ArrayList的源码的时候就可以看见ArrayList实现的接口:

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{//..
}

3.2 ArrayList的构造方法

其中,第二个的使用要注意:

注意不能把String类型的arrayList3放进Integer类型的arrayList4中,因为使用第二个构造方法时只能只能用E或者E的子类,因为arrayList3并不是arrayList4的子类类型。

4. ArrayList的扩容机制

我们来看ArrayList的不带参数的构造方法:

    public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // DEFAULTCAPACITY_EMPTY_ELEMENTDATA为0}

接着看DEFAULTCAPACITY_EMPTY_ELEMENTDATA:

    private static final int DEFAULT_CAPACITY = 10; // 指定默认容量为10private static final Object[] EMPTY_ELEMENTDATA = {}; // 空数组private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空数组transient Object[] elementData; // 类似于顺序表代码里背后的数组private int size; //有效数据个数

这个构造方法中, DEFAULTCAPACITY_EMPTY_ELEMENTDATA为0, 并没有分配数组内存,那么引出一个问题:既然没有大小,那么是怎么把数据放进顺序表的?

这个时候看我们的测试方法。

public class Test {public static void main1(String[] args) {ArrayList<Integer> arrayList1 = new ArrayList<>(); // 这行构造方法中没有找到实际调用将元素放进去的方式,那么目光往下看add方法。arrayList1.add(1); // 将数据存储于ArrayList中, 下面同理arrayList1.add(2);System.out.println(arrayList1);
}

看add方法的源码:

    public boolean add(E e) {ensureCapacityInternal(size + 1); // 假定size=0elementData[size++] = e; // 存储的时候放在最后一个元素后边return true;}

再看其中第一行ensureCapacityInternal的源码:

    private void ensureCapacityInternal(int minCapacity) { // minCapacity = size + 1 = 0 + 1 = 1ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); // elementData = 0}

再接着往下看calculateCapacity方法:

    private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 0 == 0return Math.max(DEFAULT_CAPACITY, minCapacity);   // DEFAULT_CAPACITY=10, minCapacity=1}return minCapacity; // 10}

在这个方法里可以了解到做了一个求最大值的方法, 这里为10, 那么往上返回到ensureCapacityInternal中,再进入方法ensureExplicitCapacity中:

    private void ensureExplicitCapacity(int minCapacity) { // minCapacity = 10modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0) // 10 - 0 > 0grow(minCapacity);}

看到又调用了grow:

    private void grow(int minCapacity) { // minCapacity = 10// overflow-conscious codeint oldCapacity = elementData.length; // 0int newCapacity = oldCapacity + (oldCapacity >> 1); // 0 + 0 / 2 = 0if (newCapacity - minCapacity < 0) // 0 - 10 < 0newCapacity = minCapacity; // 10if (newCapacity - MAX_ARRAY_SIZE > 0) // MAX_ARRAY_SIZE 很大这里进不来newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity); //真正分配内存了}

所以,当我们调用不带参数的构造方法的时候,只有第一个add的时候,我们才会分配大小为10的内存。

由grow()中的 int newCapacity = oldCapacity + (oldCapacity >> 1);可知, 在放第11个的时候,采用1.5倍扩容.

总结:

1. 检测是否真正需要扩容,如果是调用grow准备扩容

2. 预估需要库容的大小

初步预估按照1.5倍大小扩容

如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容

真正扩容之前检测是否能扩容成功,防止太大导致扩容失败

3. 使用copyOf进行扩容

5. ArrayList的常见操作

方法

解释

boolean add(E e)

尾插 e

void add(int index, E element)

将 e 插入到 index 位置

boolean addAll(Collection<? extends E> c)

尾插 c 中的元素

boolean remove(Object o)

删除遇到的第一个 o

E get(int index)

获取下标 index 位置元素

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)之间的元素构成一个新的ArrayList返回List<String> ret = list.subList(0, 4);System.out.println(ret);list.clear();System.out.println(list.size());
}

6. ArrayList的遍历

public class Test {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);arrayList.add(4);arrayList.add(5);int size = arrayList.size();// 通过for循环的遍历for (int i = 0; i < size; i++) {System.out.print(arrayList.get(i) + " ");}System.out.println();// 增强for遍历for (int x : arrayList) {System.out.print(x + " ");}System.out.println();// 迭代器遍历Iterator<Integer> it = arrayList.iterator();while (it.hasNext()){System.out.print(it.next() + " ");}}
}

7. 例题

1. 一个班级有若干(3个)学生,这些学生的信息有,姓名,年龄,分数(小数),考试结束后,每个学生都有分数等信息。已知每个学生对象都在ArrayList当中存放,请输出每个学生的信息?

Collections是一个用来操作集合的工具类,这个类里有非常多的方法,在里面我们用的最多的是排序方法.
class Student implements Comparable<Student>{@Overridepublic int compareTo(Student o) {return (int)(this.score - o.score);}private int age;private String name;private double score;public Student(int age, String name, double score) {this.age = age;this.name = name;this.score = score;}/** 此处省略Setter和Getter, 以及toString()  */}public class Test {public static void main(String[] args) {ArrayList<Student> arrayList = new ArrayList<>();arrayList.add(new Student(10, "小王", 49.9));arrayList.add(new Student(50, "小红", 19.9));arrayList.add(new Student(10, "大胖", 89.9));for (Student s : arrayList) {System.out.println(s);}System.out.println("==========================");Collections.sort(arrayList);for (Student s : arrayList) {System.out.println(s);}}
}

运行结果:

通过这个题我们可以总结:

(1) 我们可以在ArrayList中 存放自定义的类型

(2) 我们可以对集合进行排序, 也就是使用Collections.sort()方法

2. 给你两个字符串。

str1:"welcome to bit";
str2:"come";

请删除第一个字符串当中,出现的第二个字符串当中的字符。

预期结果:
wl t bit

要求:请使用集合ArrayList来完成

解释:

public class Test {public static ArrayList<Character> func(String str1, String str2) {ArrayList<Character> arrayList = new ArrayList<>();for (int i = 0; i < str1.length(); i++) {char ch = str1.charAt(i);if (!str2.contains(ch + "")) {  // 转为字符串arrayList.add(ch);}}return arrayList;}public static void main(String[] args) {ArrayList<Character> ret = func("welcome to bit","come");
//        System.out.println(ret);for (int i = 0; i < ret.size(); i++) {System.out.print(ret.get(i));}}
}

8. ArrayList的具体使用

8.1 简单的洗牌算法

需求: 通过代码买一副扑克牌, 没有大小王, 也没有AJQK, 只有数字1~13, 共有四种花色, 所以一共52张牌. 然后把洗牌, 将顺序打乱, 让三个人轮流揭5张牌.

(1)设计对象 - 一副牌

public class Poker {private String suit;    // 花色private int rank;   // 数字// 提供 Getter 和 Setterpublic String getSuit() {return suit;}public void setSuit(String suit) {this.suit = suit;}public int getRank() {return rank;}public void setRank(int rank) {this.rank = rank;}// 提供构造方法, 构造一张牌public Poker(String suit, int rank) {this.suit = suit;this.rank = rank;}@Overridepublic String toString() {return suit + " " + rank;}
}

(2) 买牌、洗牌、揭牌

import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class Pokers {public static final String[] SUITS = {"♥", "♠", "♣", "♦"};  // 花色// 通过这个方法买一副扑克牌, 此时是有序的public static List<Poker> buyPokers() {List<Poker> pokerList = new ArrayList<>();for (int i = 0; i < 4; i++) {   // 花色有 4个for (int j = 1; j <= 13; j++) { // 每一种花色有 13张String suit = SUITS[i];Poker poker = new Poker(suit, j);pokerList.add(poker);}}return pokerList;}// 交换public static void swap(List<Poker> pokerList, int i, int j) {Poker tmp = pokerList.get(i);pokerList.set(i, pokerList.get(j)); // 把j下标的值给到i下标pokerList.set(j, tmp);}// 洗牌public static void shuffle(List<Poker> pokerList) {Random random = new Random();for (int i = pokerList.size() - 1; i > 0; i--) {int index = random.nextInt(i);  // 假设生成的随机数为 4swap(pokerList, i, index);  // 那么4下标和i下标交换即可}}public static void main(String[] args) {List<Poker> pokerList = buyPokers();System.out.println("买牌:" + pokerList);shuffle(pokerList);System.out.println("洗牌:" + pokerList);// 揭牌: 3个人 每个人 轮流抓5张牌// 1. 描述3个人List<Poker> hand1 = new ArrayList<>();List<Poker> hand2 = new ArrayList<>();List<Poker> hand3 = new ArrayList<>();// 2. 区分 往哪个人手里放牌List<List<Poker>> hand = new ArrayList<>();hand.add(hand1);hand.add(hand2);hand.add(hand3);for (int i = 0; i < 5; i++) {for (int j = 0; j < 3; j++) {List<Poker> handTmp = hand.get(j);  // 来确定是谁的手, 在 hamdTmp 中放一张牌handTmp.add(pokerList.remove(0));   // 每次都是0下标}}for (int i = 0; i < hand.size(); i++) {System.out.println("第" + (i + 1) + "个人的牌是:" + hand.get(i));}System.out.println("剩余的牌:" + pokerList);}
}

8.2 杨辉三角

理论上说我们可以把杨辉三角的图化成下图:

而在OJ中我们可以看到, 它的返回值为List<List<Integer>>, 也就是:

class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret = new ArrayList<>();List<Integer> list1 = new ArrayList<>();list1.add(1);   // 先安排第一行, 只有一个1ret.add(list1);// 上述第一行只有1个1, 已经添加到了ret当中. 接下来我们需要从第2行开始计算for (int i = 1; i < numRows; i++) {List<Integer> curRow = new ArrayList<>();   // 当前行curRow.add(1);  // 是当前行的第一个元素, 1// 中间位置 需要计算List<Integer> prevRow = ret.get(i - 1); //前一行for (int j = 1; j < i; j++) {int num = prevRow.get(j) + prevRow.get(j - 1);curRow.add(j, num);}curRow.add(1);  // 是当前行结束元素, 1ret.add(curRow);    // 当前行加入ret中, 即结果List<List<Integer>>}return ret;}
}

9. ArrayList的问题及思考

对于顺序表ArrayList来说, 它底层是一个数组, 那么它放满了之后, 就需要扩容, 它就会产生一些问题.

比如有放满了10个元素的顺序表, 但是总共要放11个元素, 此时就需要进行一个1.5倍的扩容, 这个顺序表就变成15了, 但是只需要放11个元素, 那么就浪费了4个元素的内存空间.

所以在这里ArrayList所带来的第一个问题就是, 扩容之后, 可能会带来空间的浪费.

第二, 当前顺序表 在每次删除一个元素或者插入一个元素的时候(比如删除插入都是第一个元素), 都需要移动元素. 我们会发现它的时间复杂度达到了O(n).

于是我们就会想, 能不能有一种数据结构, 能够随用随取, 插入,删除元素的时候, 不去移动元素?

是有的, 就是链表.

1. 顺序表中间/头部的插入删除,时间复杂度为O(N)
2. 扩容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
3. 扩容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

ArrayList 不适合使用在频繁的插入和删除的场景. 它适合给定下标位置进行查找 元素。此时可以达到O(1).

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

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

相关文章

“Install Js dependencies failed“JS SDK安装失败【Bug已解决-鸿蒙开发】

文章目录 项目场景:问题描述原因分析:解决方案:解决措施1解决方案2:其他解决方案解决方案3:此Bug解决方案总结项目场景: 在下载JS SDK时,出现下载失败的情况,并显示“Install Js dependencies failed”。 在使用版本为DevEco Studio 3.0.0.601 Beta1进行低代码开发时…

世微 低功耗 PFM DC-DC 升压芯片 AP8105 干电池手持设备驱动IC

概述 AP8105 系列产品是一种高效率、低纹波、工作频率高的 PFM 升压 DC-DC 变换器。AP8105 系列产品仅需要四个外围元器件&#xff0c;就可完成将低输入的电池电压变换升压到所需的工作电压&#xff0c;非常适合于便携式 1&#xff5e;4 节普通电池应用的场合。电路采用了高性能…

mybatis快速入门(基于Mapper接口编程)

1、准备数据模型&#xff0c;建库建表 CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT AUTO_INCREMENT,emp_name CHAR(100),emp_salary DOUBLE(10,5),PRIMARY KEY(emp_id) );INSERT INTO t_emp(emp_name,emp_salary) VALUES("tom&qu…

测试相关-面试高频

测试面试相关 面试 测试的具体场景 功能测试 具体的测试工具Jmeter Postman selenium pytest 怎么看待测试的潜力与挑战 软件测试是正在快速发展&#xff0c;充满挑战的领域。尽管现在许多自动化测试软件的出现使得传统手工测试的方式被代替&#xff0c;但自动化测试工具的…

低功耗无线SOC芯片Si24R03

Si24R03是一款高度集成的低功耗无线SOC芯片&#xff0c;芯片为QFN32 5x5mm封装&#xff0c;集成了资源丰富的MCU内核与2.4G收发器模块&#xff0c;最低功耗可达1.6uA&#xff0c;极少外围器件&#xff0c;大幅降低系统应用成本&#xff0c;同时配套有成熟的开发调试软件和丰富的…

Oracle SQL优化

1、书写顺序和执行顺序 在Oracle SQL中&#xff0c;查询的书写顺序和执行顺序是不同的。 1.1SQL书写顺序如下&#xff1a; SELECTFROMWHEREGROUP BYHAVINGORDER BY 1.2 SQL执行顺序 FROM&#xff1a;数据源被确定&#xff0c;表连接操作也在此步骤完成。 WHERE&#xff1a;对…

MySQL进阶知识:SQL性能优化

目录 SQL性能分析 SQL执行频率 慢查询日志 profile详情 explain执行计划 索引的使用 最左前缀法则 范围查询 索引列运算 字符串加引号 模糊查询 or连接的条件 数据分布影响 SQL提示 覆盖索引 前缀索引 索引设计原则 SQL优化 insert优化 主键优化 页分裂 …

【Docker】安装RabbitMQ

1.拉取镜像 docker pull rabbitmq 2.运行容器 docker run \-e RABBITMQ_DEFAULT_USERitcast \-e RABBITMQ_DEFAULT_PASS123321 \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \-d \rabbitmq 3.安装管理页面的插件 进入容器内部 dock…

前端项目环境的搭建

一、下载并且安装Node&#xff08;不安装node&#xff0c;就安装nvm。nvm安装教程&#xff09;&#xff1a; 1.官网下载Node&#xff1a;https://nodejs.org/en/ 2.测试nodejs安装是否成功&#xff1a; 在windows powerShell中输入node -v 和 npm -v&#xff0c;看到版本号就…

CRM与ERP如何协同服务于企业

在当今的商业环境中&#xff0c;客户关系管理&#xff08;CRM&#xff09;和 Enterprise Resource Planning&#xff08;ERP&#xff09;是两个不可或缺的系统。它们各自独立&#xff0c;但也可以协同工作&#xff0c;以提供更高效、更全面的企业解决方案。这种协同作用可以在销…

JAVA的一些便捷性方法(Object)

在IDEA中&#xff0c;如何查看JDK的源码&#xff1f; CTRL B; 常用方法&#xff1a; 1.equals&#xff08;&#xff09; booleanequals(Object obj) 指示其他某个对象是否与此对象“相等”。 与 的比较&#xff1a; &#xff0c;即可判断基本类型&#xff0c;也…

SAE-J1939协议入门解析

文章目录 前言一、SAE J1939物理层二、SAE J1939数据链路层1、帧结构1.1、帧起始&#xff08;SOF&#xff09;1.2、优先级&#xff08;P&#xff09;1.3、扩展数据页EDP&#xff08;R&#xff09;1.4、数据页&#xff08;DP)1.5、替换远程请求Substitute Remote Request &#…

JavaScript解构数组

还记得之前我们是如何读取到数组里面的元素的么&#xff1f; const arr [2, 3, 4]; const a arr[0]; const b arr[1]; const c arr[2];然后通过这个方式去读取数组中的数据&#xff1b; 现在我们可以使用解构赋值的方法去实现 const [x, y, z] arr; console.log(x, y, …

基于视觉传感器的自主扫雷机器人设计与实现

摘要&#xff1a; 在当今的世界安全形势下&#xff0c;扫雷小车的出现可以减少各国人员在扫雷过程中的人员伤亡&#xff0c;扫雷小车实用性能强更适合在军事化领域或者是民用领域上应用。让它具有光明的发展前景。针对这一情况&#xff0c;本毕业设计就对自主扫雷小车进行研究…

Windows系统如何远程控制Realme手机?

realme使用的是realme UI系统。realme UI是realme研发的操作系统&#xff1b;realme UI 1.0基于安卓10系统&#xff0c;realme UI 2.0基于安卓11系统&#xff0c;realme UI 3.0基于安卓12系统。 对于安卓4.0及以上系统的手机&#xff0c;都可以通过软件AirDroid实现远程控制。 …

【超强笔记软件】Obsidian如何实现免费无限流量无套路云同步?

【超强笔记软件】Obsidian如何实现免费无限流量无套路云同步&#xff1f; 文章目录 【超强笔记软件】Obsidian如何实现免费无限流量无套路云同步&#xff1f;一、简介软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步1 安…

抖音自动评论助手,开发流程与需要到的技术和代码分享

先来看实操成果&#xff0c;↑↑需要的同学可看我名字↖↖↖↖↖&#xff0c;或评论888无偿分享 一、引言 随着互联网的快速发展&#xff0c;短视频平台已成为人们日常生活的重要组成部分。其中&#xff0c;抖音作为一款深受用户喜爱的短视频平台&#xff0c;拥有庞大的用户群体…

HarmonyOS开发:ArkTs常见数据类型

前言 无论是Android还是iOS开发&#xff0c;都提供了多种数据类型用于常见的业务开发&#xff0c;但在ArkTs中&#xff0c;数据类型就大有不同&#xff0c;比如int&#xff0c;float&#xff0c;double&#xff0c;long统一就是number类型&#xff0c;当然了也不存在char类型&…

【超全】C++速查手册:面向对象与继承多态

C速查手册 C 类和对象 面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠…

MySQL递归查询:洞悉数据的层层关联

在处理关系型数据库时&#xff0c;我们经常会遇到这样的情况&#xff1a;某些数据之间存在层级关系&#xff0c;例如目录、组织结构、评论等。在这些场景下&#xff0c;我们需要一种灵活的查询技术来处理这种层级关系。今天我们就来探讨MySQL中的递归查询&#xff0c;体验其独特…