【Java】还不会数组?一文万字全搞定

前言:前面两章我们详细讲解了Java基本程序设计结构中的基本知识,,包括:一个简单的Java应用,注释,数据类型,变量与常量,运算符,字符串,输入输出,控制流,大数值。 本篇将介绍最后一环——“数组”,带领大家更全面透彻地了解Java中数组的相关知识。

目录

    • 一.数组的基本概念
    • 二.数组的声明和初始化
      • 2.1数组的声明
      • 2.2数组的初始化【重要】
    • 三.访问数组元素
      • 3.1数组下标/索引
      • 3.2 for循环访问数组元素
      • 3.3 for each循环
    • 四.命令行参数
    • 五.初始JVM的内存分布
    • 六.数组中常见的各类方法
      • 6.1数组拷贝
      • 6.2数组排序
      • 6.3数组查找
      • 6.4数组填充
      • 6.5数组比较
    • 七.多维数组【二维数组】
    • 八.不规则数组

一.数组的基本概念

数组即存储着相同类型值的序列。
从定义中我不可以得到以下结论:

1.数组是一种数据结构,是用来存储同一类型值的集合;
2.数组中存放的值连续的;
3.每个空间有自己的编号,其实位置的编号为0,即数组的下标。

举个例子:在java中,包含6个整形类型元素的数组,就相当于下图中连在一起6个车位,从下图中可以看到:
在这里插入图片描述
那么,我们如何定义,使用一个数组呢?

二.数组的声明和初始化

2.1数组的声明

俗话说:变量先声明后使用。首先我们看看如何声明一个数组。
通过以下方式我们可以声明一个Java数组,在声明数组变量的时候,需要指出数组类型和数组变量的名字:

int[] array1;//array:英文单词表示数组
double[] array2;
boolean[] array3;
//...

这时我们就成功声明了一个array数组。看到这里,一些有C语言基础的小伙伴就会有一种“熟悉的陌生人”的感受,因为C语言是这样声明一个数组的:

int arr[];//C语言实现方式

两者看上去非常相似,仅仅只是“[ ]”的位置不同,实际上,在Java中,这两种形式都可以定义声明一个数组变量。只不过,大多数Java程序员更倾向于第一种方式,因为这样可以清晰地将变量类型和变量名区分开来,显得更加有逻辑性。(相当于我创建了一个名为array的变量,变量的类型是int[ ]).

2.2数组的初始化【重要】

在Java中,数组的初始化方式相对比较灵活,接下来我们一一讲解不同的初始化方式:
方法一:直接法

//对于一中我们声明的数组我们仅仅声明了变量array,并没有将它初始化为一个真正的数组
//方法一:直接初始化法
int[] array={1,2,3,4,5}//这种方式直接指明了数组中元素的值

这种方式对于C小伙伴们是最熟悉不过的,优点是简便直接,缺点是如果数组中元素个数过多,就显得比较麻烦了。
补充:这种初始化语法中不需要使用new(后文讲解),甚至不用指定长度。最后一个值后面允许有逗号,如果你要不断为数组增加值,这很方便:

String[] names={"彭于晏”,
"陈冠希",
"刘德华”,
//...
//可以在这之后添加更多的name,这个逗号是被允许的
}

方法二:新创建法

//方法二:new int[元素个数];
int[] array=new int[100];
//等价于var array=new int[100];

new int[n]语句会创建一个长度为n的数组,一旦创建了数组,就不能再改变它的长度(不过,可以改变单个数组元素)。如果程序运行过程中需要经常扩展数组大小,就应当使用另一种数据结构——“数组列表”(array list),以后会讲解。

方法三:匿名数组法

//方法三:
int[] array=new int[]{1,2,3,4,5};

这种方式会分配一个新数组并填入大括号中提供的值。它会统计初始值个数,所以new int[]中不需要指定数组个数。

补充:在Java中,允许有长度为0的数组。如果在编写一个结果为数组的方法时,这样一个长度为0的数组就很有用。可以如下创建长度为0的数组:
new elementType[0]

new elementType[] {}
注意:长度为0的数组与null并不相同!

三.访问数组元素

3.1数组下标/索引

我们以及成功声明并初始化好了一个数组,即我们准备工作已经完成,那么如何去使用一个数组呢?这时我们就需要学会去访问数组元素。
访问数组元素就需要我们找到数组元素“下标/索引”。

array[index];//通过下标/索引找到了对应数组元素

同其它程序设计语言一样,Java数组元素下标也是从0开始的,例如我们创建一个元素个数为100的数组,那么它的下标就是从0到99(而不是1到100)。一旦创建了数组,我们就可以在数组中填入元素:

int[] arrary=new int[100];
for (int i = 0; i < 100; i++) {arrary[i]=i+1;//向数组中填入数组1到100}

创建一个数字数组的时候,所有元素均初始化为0。boolean数组元素会初始化为false。对象数组元素则初始化为一个特殊值null,表示这些元素还未存放任何对象。初学者可能不解i,例如:

String[] names=new String[10];

会创建一个包含10个字符串的数组,所有的字符串均为null。如果希望这个数组包含空串,必须为元素指定空串:

 for (int i = 0; i < 10; i++) {names[i]="";
}

3.2 for循环访问数组元素

此外,在访问数组元素的时候如果需要向数组中添加或删除一个值,第一步就是要改变数组内容,第二步在访问新数组元素的时候我们还需要修改数组元素个数。在Java中提供了一种array.length方法可以获取数组中元素个数,再通过for循环访问数组元素,例如:

 int[] a=new int[]{12,3,46,5,5,5,2,879};for (int i = 0; i < a.length; i++) {System.out.println(a[i]);
}

最后就是一个老生常谈的bug了——数组不能越界访问!
例如:我们创建了一个100个元素的数组,并试图访问array100,就会引发如下异常:
在这里插入图片描述
即表明你访问了一个越界的数组元素,这是不被允许的。

3.3 for each循环

虽然上一篇中我们已经提到了for each循环,但是由于它在数组中是一种较为新颖的循环,我们再次在这里提及它。
for each循环是Java中一种功能很强的循环结构,可以用来依次处理数组(或者其它元素集合)中的每个元素,==而不必考虑指定下标值。==这也是它区别与普通for循环最大的不同。
其格式为下:

for(变量:集合) statement

它定义一个变量用于暂存集合中的每一个元素,并执行相应语句(或语句块)。集合的表达式必须是一个数组或者是一个实现了Iterable接口的类对象(例如ArrayList,以后会讲解)。例如:

int[] a=new int[]{1,2,3,4,5};
for(int element:a)System.out.println(element);/*12345*/

打印数组a的每一个元素,一个元素占一行。
实际上,这个循环应该读作“循环a中的每一个元素”(for each element in a)这也是它名字由来。
相比于传统for循环for each循环语句显得更加简洁,更不易出错,因为你不必因为下标的起始值和终止而操心。以下是二者对比:

//二维数组 就是一个特殊的一维数组
for (int i = 0; i < array.length; i++) {for (int j = 0; j < array[i].length; j++) {System.out.print(array[i][j]+" ");}System.out.println();
}/**/System.out.println("=====");for(int[] tmpArray : array) {for(int x : tmpArray) {System.out.print(x+" ");}System.out.println();
}

注意:for each循环语句的循环变量会遍历数组中的每个元素,而不是下标值。

此外,如果你仅仅想打印出数组中的所有值,那么Java中有一个更加简单的方式,即利用Array类中的toString方法,调用Array.toString(a),返回一个包含数组元素的字符串,这些元素包含在中括号内,并用逗号分隔开。例如:
在这里插入图片描述
结果如下:
在这里插入图片描述
注意引入包:import java.util.Arrays;

此外,我们还可以自我实现一个myToString方法:

   public static String myToString(int[] array) {String ret = "[";for (int i = 0; i < array.length; i++) {ret = ret + array[i];if(i != array.length-1) {ret += ", ";}}ret += "]";return ret;}

四.命令行参数

前面已经看到多个使用Java数组的示例。每一个Java应用程序都有一个带String[] args参数的main方法。这个参数表明main方法将接收一个字符串数组,也就是命令行参数。例如,看一看下面这个程序:

public class Test{public static void main(String[] args){if (args[0]. equals("-h"))System.out. print("Hello, ");else if (args[0]. equals("-g"))System. out.print("Goodbye, ");// print the other command-line argumentsfor (int i = 1; i < args. length; i++)System.out. print(" "+ args[i]);System.out.println("!");}
}

如果使用java Test -g cruel world命令调用这个程序,args数组将会包含一下内容:args[0]=“-g” args[1]=“cruel” args[2]=“world”。这个程序就会显示下面这个信息:
在这里插入图片描述

五.初始JVM的内存分布

在深入了解数组的使用之前,我们现要了解一下JVM的内存分布,可是我们为什么要了解这个东西呢?
我们知道,Java的程序是跑在虚拟机(即JVM)上,我们要想理解数组这一引用类型是如何引用变量的,就必须了解其它JVM上的内存是如何分配的。
首先,JVM对所使用的内存按照功能的不同进行了划分:
在这里插入图片描述
解释一下里面的各个部分:

  • 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址
  • 虚拟机栈(JVM Stack): 与方法调用相关的一些信息,每个方法在执行时,都会先创建一个栈帧,栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息,保存的都是与方法执行时相关的一些信息。比如:局部变量。当方法运行结束后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
  • 本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的
  • 堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3,4,5} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销
    毁。
  • 方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域

简单解释一下这里为什么会出现两个栈区:我们知道JVM底层是由C/C++实现的,而本地方法栈中就包含了一些由C/C++程序实现的方法。而虚拟机栈才是我们平时所说的栈区。
现在我们只简单关心堆 和 虚拟机栈这两块空间,后序JVM中还会更详细介绍。

六.数组中常见的各类方法

6.1数组拷贝

在Java中,允许将一个数组变量拷贝到另一个数组变量中去,这时,两个变量将引用同一个数组

        int[] smallPrimes=new int[10]; int[] luckyNumbers=new int[10];luckyNumbers[5]=12;luckyNumbers=smallPrimes;//smallPrimes[5]==12

在这里插入图片描述

正常来说我们自己是可以很轻松实现一个数组拷贝的方法的:

   public static int[] copyArray(int[] array) {int[] copy = new int[array.length];for (int i = 0; i < array.length; i++) {copy[i] = array[i];}return copy;}

但Java中提供了更便捷的Arrays类的copyOf方法:

luckyNumbers=Arrays.copyOf(luckyNumbers,luckyNumbers.length);
//第一个参数是要拷贝的原始数组
//第二个参数是新数组的长度

这个方法通常用来增加数组大小

luckyNumbers=Arrays.copyOf(luckyNumbers,2*luckyNumbers.length);

如果数组元素是数值型,那么额外的元素将被赋值为0;如果数组元素是布尔型,则将赋值为false。相反,如果长度小于原始数组的长度,则只拷贝前面的值。
此外,还有类似的Arrays类的copyOfRange方法:

public static void main(String[] args) {int[] array = new int[] { 1,2,3,4 };int[] ret = Arrays.copyOfRange(array,2,4);//第一个参数:要拷贝的原始数组//第二个参数from:表示要拷贝的起始位置//第三个参数to:表示要拷贝的终止位置System.out.println(Arrays.toString(ret));//[3,4]
}

Java数组与堆栈上的C++数组有很大的不同,但基本上与在**堆(heap)**上分配的数组指针一样,也就是说:
int[] a=new int[100];//Java
不同于
int[] a[100];//C++
而等同于
int* a=new int[100];//C++
表明Java中数组变量存储的本质上是一个地址,通过这个地址“引用”到堆区上的目标对象。
同时,Java中的[ ]运算符被预定义为会完成 越界检查,而且没有指针运算,即不能通过a+1得到数组中的下一个元素。

6.2数组排序

我们之前对数组常用的排序是冒泡排序,这里我们再次回顾一下:

public static void bubbleSort(int[] array){//i表示循环的趟数for (int i = 0; i < array.length-1; i++) {boolean flag=false;for (int j = 0; j < array.length-1-i; j++) {//从小到大排序if(array[j]>array[j+1]) {int tempArray = array[j];array[j]=array[j+1];array[j+1]=tempArray;flag=true;}}if(flag==false)return;}}public static void main(String[] args) {int[] a=new int[]{1,3,2,6,0,9};bubbleSort(a);for (int b:a) {System.out.print(b+" ");}//0 1 2 3 6 9}

要想对数值型数组进行排序,我们还可以使用Java中Arrays类的sort方法:

int[] a=new int[10000];
Arrays.sort(a);

这个方法使用了优化的快速排序算法。快速排序算法对于大多数数据集合来说都是效率比较高的。
接下来,我们通过一个经典案例练习一下——“抽彩游戏”:

问题描述:
抽彩是从多个数字中随机抽取几个不重复的值,进行排序输出且判断是否中奖。若中奖则输出中奖次数,若未中奖则给出提示。
在这里插入图片描述

示例代码如下:

import java.util.Arrays;
import java.util.Scanner;public class LotteryDrawing {public static void main(String[] args) {int count = 0;//定义一个计量数,计算中奖了几次Scanner sc = new Scanner(System.in);System.out.println("请输入您要抽取数字的最高数:");int n = sc.nextInt();//设定一个n存放最高位数值int n1 = n;//定义了一个n1与n的数值相同System.out.println("请输入您要抽取几个数字(1~"+n+"):");int k = sc.nextInt();//设定了抽取数if(k>n){System.out.println("对不起,您输入的数字不符合规范!");//若此时抽取数比最高数要高则报错}else{int[] numbers1 = new int[n];int[] numbers2 = new int[n1];//定义了两个数组,其长度分别与n和n1相同for (int i = 0; i < numbers1.length; i++) {numbers1[i] = i+1;//对数组numbers进行从1~n的赋值;}for (int i = 0; i < numbers2.length; i++) {numbers2[i] = i+1;//对数组numbers2进行从1~n1的赋值;}int[] result = new int[k];//抽取结果//定义了result数组使其长度等于抽取数kfor (int i = 0; i < result.length; i++) {int r =(int) (Math.random()*n);//Math.random()*n会得到一个0到n-1之间的随机数,左闭右开!//抽取随机数的本质是抽取随机下标result[i] = numbers1[r];//选择随机数numbers[r]赋值给result[i]numbers1[r] = numbers1[n - 1];n--;//这里确保了不会再次抽取到同一个值}int[] winning = new int[k];//中奖结果for (int i = 0; i < winning.length; i++) {int w = (int) (Math.random()*n);winning[i] = numbers2[w];numbers2[w] = numbers2[n1 - 1];n1--;}Arrays.sort(result);//对数组进行排序System.out.println("抽取完成,您抽取的数为:");for(int r :result){System.out.print(r+" ");}//使用foreach循环对数组进行遍历System.out.println("");//换行Arrays.sort(winning);System.out.println("中奖数为:");for (int w:winning){System.out.print(w+" ");}for (int x = 0; x < result.length; x++) {for (int y = 0; y < winning.length; y++) {if(result[x] == winning[y]){count++;}}}//使用两个for循环且利用if语句对数组的值进行判断//若有相同值则count计数值自增System.out.println();if(count == 0){System.out.println("对不起,您未中奖,请再接再厉!");}else{System.out.println("恭喜您,您中奖了"+count+"次");}}}
}

这个案例综合了数组排序的相关内容,仔细研读定会有所收获。

6.3数组查找

在数组使用中,有时我们需要在数组中找到目标元素,这时候我们就需要了解一些数组查找的方法:
方法一:直接暴力查找

  public static int findNum(int[] array,int key) {for (int i = 0; i < array.length; i++) {if(array[i] == key) {return i;}}return -1;//因为直接法是挨个查找,所以效率很低}

这种方式是最直接最简单但效率最为低下的方式,仅限数组大小较小时使用。
方法一:二分查找

 public static int binarySearch(int[] array,int key) {int left = 0;int right = array.length-1;while (left <= right) {int mid = (left+right) / 2;if(array[mid] == key) {return mid;}else if(array[mid] > key) {right = mid - 1;}else {left = mid + 1;}}return -1;}

这个方法相比于方法一效率还是提升了不少的。
对于数组查找,当然Java也提供了相应的方法Arrays类的binarySearch方法:

Arrays.binarySearch(int[] a,key);

具体使用方法就不必多说了,直接用!
Java当然不止提供了这一种排序方法,借助Java帮助手册我们可以自行查询相应方法和参数,结合实际情况和对应具体功能合理选择。

6.4数组填充

有时我们定义完数组后想要对其初始化一般是用for循环解决。
而Java中提供了Arrays类的fill方法:
功能:对数组内容进行指定填充。

public static void main(String[] args) {int[] array = new int[10];Arrays.fill(array,5);Arrays.fill(array,4,6,10);System.out.println(Arrays.toString(array));//[5, 5, 5, 5, 10, 10, 5, 5, 5, 5]
}

6.5数组比较

在上一篇中我们提到了数组之间的比较一定不能使用“ ==”比较 ,如果相等仅仅只能表明两个数组存储在相同的位置,而不能表示两个数组存储的内容是完全等同的。
而Java中提供的Arrays类的equals方法实现了数组的比较:

public static void main(String[] args) {int[] arr1 = new int[] { 5,4,3,2,1 };int[] arr2 = new int[] { 1,2,3,4,5 };int[] arr3 = new int[] { 1,2,3,4,5};System.out.println(Arrays.equals(arr1, arr2));//falseSystem.out.println(Arrays.equals(arr2, arr3));//true
}

七.多维数组【二维数组】

多维数组中我们主要围绕最常见的二维数组展开讨论,这里我们就不详细一一解释了,因为它和一维数组大同小异:

      //二维数组的声明和初始化//以Int为例,//法一:静态初始化int[][] list={{123}{4,5,6},{7,8,9}};//法二:动态初始化int[][] list=new int[5][10];//法三:列数不确定int[][] list=new int[5][];//此时所有的一维数组都没有开辟内存空间,它们的地址都为 null;

这里举一个案例,观察一下二维数组在JVM中的内存分布:
在这里插入图片描述
实际上,二维数组的本质就是一个存储着一维数组的数组,它的各个一维数组的内存大小可以相同,也可以不相同。(不规则数组)
对于二维数组的访问我们跟一维数组类似,也有两种实现方式:

int[][] list={{1,2,3},{4,5,6},{7,8,9}};
//法一:for (int i = 0; i < list.length; i++) {for (int j = 0; j < list[0].length; j++) {System.out.print(list[i][j]+" ");}System.out.println();
}System.out.println("==================");
//法二:
for (int[] x :list) {for (int y:x) {System.out.print(y+" ");}System.out.println();
}
/*
1 2 3 
4 5 6 
7 8 9 
==================
1 2 3 
4 5 6 
7 8 9 */}

八.不规则数组

刚才我们提及了二维数组可以省略行初始化,即:

int[][] list=new int[5][];

为什么可以这样呢?我们知道,二维数组本质上是一个存储着一维数组的数组。列数的不确定可以使我们对数组进行更加灵活的处理,即可以方便地构造一个“不规则”数组,即数组的每一行都有不同的长度
下面我们通过一个杨辉三角案例具体了解一下不规则数组的实现:

问题描述:
在这里插入图片描述

示例代码如下:

    public static void main(String[] args) {int[][] a = new int[10][];for (int i = 0; i < a.length; i++) {// 给二维数组中每一个一维数组在堆上开辟内存空间a[i] = new int[i + 1];// 遍历每一个一维数组,赋值for (int j = 0; j < a[i].length; j++) {// 每一行的第一个元素和最后一个元素都是1if (j == 0 || j == a[i].length - 1) {a[i][j] = 1;} else {// 每一行非第一个元素和最后一个元素的值 = 上一行的同一列 + 上一行的上一列a[i][j] = a[i - 1][j] + a[i - 1][j - 1];}}}// 输出杨辉三角for (int i = 0; i < a.length; i++) {for (int k = 0; k < a[i].length; k++) {System.out.print(a[i][k] + "\t");}System.out.println();}
}

总结:本篇详细讲解了Java中数组的使用,我们不能发现,其实许多功能和方法Java中都有相应的封装好的类方法供你使用,一方面我们要去了解怎么实现,但更重要的是要学会去自行检索各类方法然后快速上手使用。本篇到此结束,看到这里实属不易,您的支持与鼓励是我前进最大的动力!也希望屏幕前的你能有所收获。

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

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

相关文章

写爬虫代码抓取Asterank中小行星数据

2024年5月4日 问题来源 解决方案 回顾2023年7月14日自己写的爬虫代码 import requests import re import pandas as pd texts[] def getData(page):#每页评论的网址urlhttps://item.jd.com/51963318622.html#comment#添加headers&#xff0c;伪装成浏览器headers{User-Agent:…

即插即用 | YOLOv8热力图可视化方法详解,揭秘AI如何「看」世界!【附完整源码】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

vivado 低级别 SVF JTAG 命令、多链 SVF 操作

多链 SVF 操作 以下示例显示了如何在 SVF 链上处理操作。 每个链中连接有 2 个器件 &#xff1a; xcku11 和 xcku9 。配置存储器连接到链中的第 2 个器件 (xcku9) 。为访问此配置存储器 &#xff0c; SVF 会使用 HIR 、 HDR 、 TIR 和 TDR 命令来生成命令。为刷写此…

路由模块封装

目录 一、问题引入 二、步骤 一、问题引入 随着项目内容的不断扩大&#xff0c;路由也会越来越多&#xff0c;把所有的路由配置都堆在main.js中就不太合适了&#xff0c;所以需要将路由模块抽离出来。其好处是&#xff1a;拆分模块&#xff0c;利于维护。 二、步骤 将路由相…

小巧简单实用的Linux端口转发工具Rinetd

Linux下实现端口转发有很多种方法&#xff0c;尤其是在可以联网的情况下&#xff0c;更是容易。最近在资源受限的定制系统中&#xff0c;找到一个方便离线安装和使用的端口转发工具Rinetd&#xff0c;安装包仅几十K&#xff0c;而且有很多版本的Linux发行系统的支持。 1、安装…

Spring底层入门(九)

boot的执行流程分为构造SpringApplication对象、调用run方法两部分 1、Spring Boot 执行流程-构造 通常我们会在SpringBoot的主启动类中写以下的代码&#xff1a; 参数一是当前类的字节码&#xff0c;参数二是main的args参数。 public class StartApplication {public static…

解决jar包中没有主清单目录的问题

文章目录 解决jar包中没有主清单目录的问题问题描述环境描述方法一 | 阿里巴巴构造器的通用解决方案方式二 | 指定MANIFEST.MF路径 解决jar包中没有主清单目录的问题 问题描述 很简单可能很多人都遇到过&#xff0c;maven项目打成jar包后执行报错&#xff1a;jar包中没有主清单…

ai可以做思维导图吗?当然是可以的!

ai可以做思维导图吗&#xff1f;在快节奏的现代生活中&#xff0c;思维导图作为一种高效的信息组织和表达工具&#xff0c;越来越受到人们的青睐。随着人工智能&#xff08;AI&#xff09;技术的不断发展&#xff0c;AI思维导图软件也应运而生&#xff0c;它们不仅能够帮助用户…

Orange3数据可视化(小提琴图)

小提琴图 小提琴图和箱线图类似&#xff0c;用来显示数据分布和概率密度。结合了箱线图和密度图的特征&#xff0c;用来显示数据的分布形状。 输入 数据: 输入数据集 输出 选中的数据: 从图中选中的实例 数据: 增加了一列&#xff0c;显示数据点是否被选中 …

three.js 效果细节提升

1. three.js 效果细节提升 加载模型时&#xff0c;给模型设置接受阴影&#xff0c;反射阴影 gltfLoader.load("./model/court-transformed.glb", (gltf) > {gltf.scene.traverse(child > {if (child.isMesh) {child.castShadow true; // 设置阴影可以投射阴…

【Linux】yum与vim

文章目录 软件包管理器&#xff1a;yumLinux安装和卸载软件包Linux中的编辑器&#xff1a;vimvim下的底行模式vim下的正常模式vim下的替换模式vim下的视图模式vim下的多线程 软件包管理器&#xff1a;yum yum其实就是一个软件,也可以叫商店 和你手机上的应用商店或app store一…

【C++】详解STL容器之一的deque和适配器stack,queue

目录 deque的概述 deque空间的结构 deque的迭代器 deque的数据设计 deque的优缺点 适配器的概念 ​编辑 stack的概述 stack的模拟实现 queue的概述 queue的模拟实现 deque的概述 deque的设计参考了另外两大容器vector和list。可参考下面两篇文章 详解vector&#x…

Spring Boot 整合 socket 实现简单聊天

来看一下实现的界面效果 pom.xml的maven依赖 <!-- 引入 socket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- 引入 Fastjson &#x…

bert-NER 转化成 onnx 模型

保存模型 加载模型 from transformers import AutoTokenizer, AutoModel, AutoConfigNER_MODEL_PATH ./save_model ner_tokenizer AutoTokenizer.from_pretrained(NER_MODEL_PATH) ner_config AutoConfig.from_pretrained(NER_MODEL_PATH) ner_model AutoModelForTokenCl…

【雅思写作】Vince9120雅思小作文笔记——P1 Intro(前言)

文章目录 链接P1 Intro&#xff08;前言&#xff09;字数限制题型综述&#xff08;problem types overview&#xff09;1. **柱状图&#xff08;Bar Chart&#xff09;** - 描述不同类别在某个或多个变量上的数据量比较。2. **线图&#xff08;Line Graph&#xff09;** - 展示…

冯喜运:5.10黄金反弹受阻,原油EIA库存激增引发市场情绪

【黄金消息面分析】&#xff1a;据最新市场数据显示&#xff0c;现货黄金在周四欧市早盘经历了显著下滑&#xff0c;价格一度跌破2310美元/盎司的关口&#xff0c;日内高点回落达10美元&#xff0c;截至发稿&#xff0c;黄金小幅反弹&#xff0c;交投于2312美元/盎司附近。此番…

【工具】如何提取一个mp4文件的关键帧

文章目录 怎么做如何安装ffmepgUbuntu 或 DebianCentOS 或 FedoramacOSWindows其他 Linux 发行版 实践什么是关键帧 怎么做 你可以使用ffmpeg这个强大的多媒体处理工具来提取mp4文件中的关键帧。以下是一个示例命令&#xff0c;可以使用ffmpeg从mp4文件中提取关键帧&#xff1…

即将开幕,邀您共赴创新之旅“2024上海国际消费者科技及创新展览会”

备受期待的2024上海国际消费者科技及创新展览会&#xff08;以下简称“CTIS”&#xff09;即将于6月13日至15日亮相上海新国际博览中心N1-N3馆。 2024上海国际消费者科技及创新展览会总面积达40,000平方米&#xff0c;涵盖600余家展商&#xff0c;预计吸引40,000多位观众莅临现…

单片机——直流电机

1 .关于4线直流电机 两根12v供电线&#xff0c;通入12v&#xff0c;风扇以最高转速工作。 一根测速线&#xff0c;电机工作时输出测速信号&#xff0c;提供转速反馈。一根PWM控制信号线&#xff0c;电机工作时控制器输入PWM控制信号&#xff0c;以控制风扇转速(通常为占空比可…

Python爬虫基础知识学习(以爬取某二手房数据、某博数据与某红薯(书)评论数据为例)

一、爬虫基础流程 爬虫的过程模块化&#xff0c;基本上可以归纳为以下几个步骤&#xff1a; 1、分析网页URL&#xff1a;打开你想要爬取数据的网站&#xff0c;然后寻找真实的页面数据URL地址&#xff1b; 2、请求网页数据&#xff1a;模拟请求网页数据&#xff0c;这里我们介…