Java--一维二维数组的使用,探索Arrays类方法魅力

郑州吴彦祖772 2024-10-17 13:05:01 阅读 85

各位看官:如果您觉得这篇文章对您有帮助的话

欢迎您分享给更多人哦

感谢大家的点赞收藏评论,感谢您的支持

c74aa267346f4a60b3edbe51bce6243b.png

!!!

一:数组的概念以及定义,初始化

1.1:数组概念以及定义

数组概念:可以看成是

相同类型元素的一个集合

数组定义:三种方法

T

[]

数组名

=

new

T

[

N

];例如:int[]arr = new arr[10];

T

:表示数组中存放元素的类型

T[]:表示数组的类型

N

:表示数组的长度

例如:

int

[]

array1

=

new

int

[

10

];

//

创建一个可以容纳

10

int

类型元素的数组

double

[]

array2

=

new

double

[

5

];

//

创建一个可以容纳

5

double

类型元素的数组

String

[]

array3

=

new

String

[

3

];

//

创建一个可以容纳

3

个字符串元素的数组

1.2:数组的初始化主要有两种:动态初始化以及静态初始化

     1.静态初始化和动态初始化一步完成

数组动态初始化:在创建数组时,直接指定数组中元素的个数

int

[]

array

=

new

int

[

10

];这种初始化,这个arr数组里面的值都为0;

静态初始化:在创建数组时不直接指定数据元素个数,而直接将具体的数据内容进行指定

静态初始化虽然没有指定数组的长度,编译器在编译时会根据

{}

中元素个数来确定数组的长度

 语法格式:

T[]

数组名称

= {data1, data2, data3, ..., datan};

例如:

int

[]

array1

=

new

int

[]{

0

,

1

,

2

,

3

,

4

,

5

,

6

,

7

,

8

,

9

};

double

[]

array2

=

new

double

[]{

1.0

,

2.0

,

3.0

,

4.0

,

5.0

};

String

[]

array3

=

new

String

[]{

"hell"

,

"Java"

,

"!!!"

};

静态初始化可以省略可以省去后面的new int[];

直接就是 

int

[]

array1

=

{

0

,

1

,

2

,

3

,

4

,

5

,

6

,

7

,

8

,

9

};

但是这种初始化是严令禁止的:

int

[]

array1

=

new

int

[10]{

0

,

1

,

2

,

3

,

4

,

5

,

6

,

7

,

8

,

9

};,

编译器会报错误

     2.同时静态初始化和动态初始化也可以分为两步:

int

[]

array1

;

array1

=

new

int

[

10

];

int

[]

array2

;

array2

=

new

int

[]{

10

,

20

,

30

};

// 注意省略格式不可以拆分, 否则编译失败

// int[] array3;

// array3 = {1, 2, 3};

这样不可以,!!!只能在定义的时候进行赋值

1.如果没有对数组进行初始化,数组中元素有其默认值:

2.如果数组中存储元素类型为引用类型,默认值为null

二:数组的使用:

1.1:数组的访问:

数组下表访问不能越界:

int

[]

array

=

{

1

,

2

,

3

};

System

.

out

.

println

(

array

[

3

]);

//

数组中只有

3

个元素,下标一次为:

0 1 2

array[3]

下标越界

数组越界异常

1.2:数组遍历

1.一般C中我们都是循环遍历:但是java中注意:在数组中可以通过 数组对象.length 来获取数组的长度

int

[]

array

=

new

int

[]{

10

,

20

,

30

,

40

,

50

};

for

(

int

i

=

0

;

i

<

array

.

length

;

i

++

){

System

.

out

.

println

(

array

[

i

]);

}

2.java也可以使用for-each遍历数组:

int

[]

array

=

{

1

,

2

,

3

};

for

(

int

x

:

array

) {

System

.

out

.

println

(

x

);

}

2:数组是引用类型

2.1:要了解数组首先,要了解引用到底是什么?

在java里 数据类型分为两大类:基本数据类型(Primitive Types)和引用数据类型(Reference Types)。引用数据类型是相对于基本数据类型而言的,它们不是直接在内存中存储数据值,而是存储数据的引用(或者说是指向数据的内存地址)。

Java中的引用数据类型主要包括以下几类:

类,数组,枚举,接口,注解

我们现在现在需要注意这两项:

类(Class Types):类是Java程序的基本构建块,用于创建对象。每个对象都是类的一个实例,而类本身就是一种引用数据类型。你可以定义自己的类来封装数据和逻辑,Java标准库中也提供了大量的类供我们使用。

数组(Array Types):数组是一种特殊的引用类型,用于存储固定大小的同类型元素。数组可以是基本数据类型的数组,也可以是引用数据类型的数组(比如对象数组或另一个数组的数组)。

2.2:初始JVM的内存分布:

内存是一段连续的存储空间,主要用来存储程序运行时数据的。比如:

1.

程序运行时代码需要加载到内存

2.

程序运行产生的中间数据要存放在内存

3.

程序中的常量也要保存

4.

有些数据可能需要长时间存储,而有些数据当方法运行结束后就要被销毁

如果对内存中存储的数据不加区分的随意存储,那对内存管理起来将会非常麻烦。比如:

因此

JVM

也对所使用的内存按照功能的不同进行了划分:

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

2.3基本类型变量与引用类型变量的区别

基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;

引用数据类型创建的变量,一般称为对象的引用,存储的是对象所在空间的地址的变量。

从上图可以看到,

引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该

地址,引用变量便可以去操作对象

。有点类似

C

语言中的指针,但是

Java

中引用要比指针的操作更简单。

再看一个例子:

2.4:空指针:null

null

Java

中表示

"

空引用

" ,

也就是一个不指向对象的引用

.

int

[]

arr

=

null

;

System

.

out

.

println

(

arr

[

0

]);

//

执行结果

Exception in thread

"main"

java

.

lang

.

NullPointerException

at Test

.

main

(

Test

.

java

:

6

)

null

的作用类似于

C

语言中的

NULL (

空指针

),

都是表示一个无效的内存位置

.

因此不能对这个内存进行任何读写操 作.

一旦尝试读写

,

就会抛出

NullPointerException.

注意

: Java

中并没有约定

null

0

号地址的内存有任何关联

3:数组应用场景:

3.1:数组作为函数参数:一张图弄懂

总结

:

所谓的

"

引用

"

本质上只是存了一个地址(还不是真的内存地址)

. Java

将数组设定成引用类型

,

这样的话后续进行数组参数传参

,

其实只是将数组的地址传入到函数形参中.

这样可以避免对整个数组的拷贝

(

数组可能比较长

,

那么拷贝开销就会很大

).

3.2:数组作为函数的返回值

public class Test {

public static int[] func(){

int []array = new int[]{1,2,3,4,5};

return array;

}

实话说这个array数组是个临时变量,在C里面func返回时会被销毁,但是在java里面这个还是一直存在的就不会销毁

public static void main(String[] args) {

int[] ret = func();

for (int i = 0; i < ret.length; i++) {

System.out.println(ret[i]);

}

}

}

4:数组练习:

4.1:数组转化为字符串Arrays.toString

<code> public static String myToString(int[] arr) {

String ret = "[";

for (int i = 0; i < arr.length; i++) {

ret += arr[i];

if (i != arr.length - 1) {

ret += ",";

} else {

ret += "]";

}

}

return ret;

}

public static void main(String[] args) {

int[] arr = {1, 2, 3, 4};

String ret = myToString(arr);

System.out.println(ret);

}

}

注意ret是String类型,每次都是ret+=……,最后直接打印

但是

Arrays.toString这个方法直接帮我们数组转化为字符串:

 4.2:拷贝方法:Arrays.copyOf Arrays.copyOfRange

巧了,我们java里面已经帮我们实现好了:Arrays.copyOf这个方法(这个方法里面的参数(换个类型)还是有很多的,一起构成了方法的重载)

public static void main(String[] args) { //Arrays.copyOf(),Arrays.copyOfRange()

int[] arr = {1, 2, 3, 4};

int[] copy = Arrays.copyOf(arr, arr.length * 2);

//并且这里我们还可以进行两倍的拷贝,因为这个数组没有长度嘛,不用考虑越界的问题

System.out.println(Arrays.toString(copy));

还可以选择拷贝:

int[] copy2 = Arrays.copyOfRange(arr, 1, 2);但是这个是从arr数组内部拷过来的

System.out.println(Arrays.toString(copy2));

}

这里大家可以发现打印的有12个因为是[1,13)左闭右开,,但是arr从1开始里面只有3个数,然后就只能copy3个数然后补0

那这些方法的源码是怎么实现的呢:大家可以看我这张图

但是源代码实现的话又会有一些的的问题:就不能拷贝上述的12个了

我们尽量还是用Arrays.copyOfRange这个方法

注意:

数组当中存储的是基本类型数据时,不论怎么拷贝基本都不会出现什么问题,但如果存储的是引用数据类 型,拷贝时需要考虑深浅拷贝的问题,关于深浅拷贝在后续详细给大家介绍

4.3:二分查找以及排序方法:

二分查找:针对

有序数组

,返回的值返回的是最后一次的位置left然后 -(left+1)

所以说按下面这个数组,key每次都>10的话,每次返回都是-9

这是我模仿源码的方法写的

<code>public class Test {

public static void main(String[] args) {

int []arr = {1,2,3,4,5,6,7,8,9};

int key =7;

int ret = binarySearch(arr,arr.length,key);

System.out.println(ret);

}

public static int binarySearch(int []arr,int sz,int key){

int left = 0;

int right = sz-1;

while(left < right){

int mid = (left +right)>>>1;//这个右移一位就很秒

if(arr[mid] < key){

left = mid + 1;

}

else if(arr[mid]>key){

right = mid -1;

}else{

return mid;

}

}

return -(left+1);

}

}

源码:

但是如果不是有序地呢,我们可以自己实现一个冒泡排序

以及配合的找数字的,但是java里面已经帮我们实现的有方法了——Arrays.sort

以及配合找数字的Arrays.binarySearch

不过返回的值就是拍完序之后的位置了,这个一定要注意!!!

二分查找优点:针对一个长度为

10000

个元素的数组查找

,

二分查找只需要循环

14

次就能完成查找

.

随着数组元素个数 越多,

二分的优势就越大

.

4.4:填充方法以及比较方法:

填充也可以指定范围:java 太妙啦!!!

4.5:数组求平均值

代码两个注意点

1:首先使用 for -each遍历数组时,这里的X其实就是数组里面的值

2:最后求平均值一定要强转成double 类型

<code>public static void main(String[] args) {

int[] arr = {1,2,3,4,5,6};

System.out.println(avg(arr));

}

public static double avg(int[] arr) {

int sum = 0;

for (int x : arr) {

sum += x;//注意这个

}

return (double)sum / (double)arr.length;//注意

}

三:二维数组的使用

1.二维数组的4种定义方式

二维数组是特殊的一维数组

二维数组的定义方法:一般就是这三种

int [][] array = { {1,2,3},{4,5,6}};

int [][] array1 = new int[][]{ {1,2,3},{4,5,6}};

int [][] array2 = new int[2][3];

但是二维数组还可以不指定列,只指定行(和C语言相反)(第四种)

int [][] array = new int[2][];

String ret = Arrays.toString(array);

System.out.println(ret);

(这个时候就相当于,只初始化了两个值,array[0],array[1],他们两个的值默认都是null(这个时候就完全可以看出来array(二维数组就是特殊的一维数组)))

然后我可以这样给他赋值

int [][] array = new int[2][];

array[0] = new int[]{1,2,3};

array[1] = new int[]{1,2,3,4,5,6};

2.二维数组的遍历:

我们上述描述过了一维数组(array)的长度是array.length,我们现在又知道了二维数组又是特殊的一维数组譬如上述的array[2][],那么它的长度就是array.length,它经过初始化之后array[1].length就是3

那么我们有了上述的知识之后就可以写出下面的代码

<code> int [][] array = new int[][]{ {1,2,3},{4,5,6}};

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();// 打印一行换行

}

3.二维数组的打印

那我们这样打印呢?

<code> int [][] array = new int[][]{ {1,2,3},{4,5,6}};

System.out.println(array[0]);

System.out.println(array[1]);

打印的不是实际的地址是经过修改的地址,实际上是

最后调用的是 toString方法

再看看接下来打印的是什么呢?

<code> int [][] array = new int[][]{ {1,2,3},{4,5,6}};

System.out.println(array[0]);

System.out.println(array[1]);

System.out.println("=============");

System.out.println(Arrays.toString(array[0]));

System.out.println(Arrays.toString(array[1]));

System.out.println("=============");

System.out.println(array[0].length);

System.out.println(array[1].length);

System.out.println("=============");

System.out.println(array.length);

System.out.println("=============");

这个呢?

<code> int [][] array = new int[][]{ {1,2,3},{4,5,6}};

System.out.println(Arrays.toString(array));

System.out.println(Arrays.deepToString(array));

上述就是的Java—数组的使用和定义全部内容了,相信您能看到这里,一定是对小编有了一定的认可,如果有任何错误

 欢迎各位大佬评论区留言修正或者直接私信我!!!

您的支持就是我最大的力量​​​

bcb51650eac54f748f693cdc5b00f9a6.png

2d8b40093abe47c7b347cdd7c906e87f.gif



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。