Java数据结构篇一:数组详解

[本篇参考地址见底]  项目开发中,如果需要存储大量的数据,例如如果需要读取100个数,那么就需要定义100个变量,显然重复写100次代码,是没有太大意义的。Java语言提供了数组(array)的数据结构,可以解决这个问题。

数组的概念

一个数组是相同数据类型的元素按一定顺序排列的集合。使用数组可以将同一类型的数据存储在连续的内存位置。数组中各元素的类型相同,通过下标的方式来访问数组中的元素,下标从0开始。

由此得出,数组具有以下基本特点:

┡ 数组的长度是确定的,数组一旦被创建,它的大小就是不可以改变的。

┡ 数组的元素必须是相同类型,不能出现混合类型。

┡ 数组类型可以是任意数据类型,包括基本数据类型和引用类型。

一维数组

数组在使用之前必须先声明,也就是要先定义后使用。一维数组的定义格式为:

┡ 数据类型[] 数组名;

┡ 数据类型 数组名[];

这两种声明方式完全等价,不过在实际开发中,我们一般推荐使用第一种方式。

数组的初始化

数组声明之后,仅仅是定义了一个数组引用,系统并没有为数组分配任何内存,因此现在还不能访问它的任何元素。必须经过数组初始化后,才能使用数组的元素。

数组的初始化分为静态初始化和动态初始化两种。

┡ 静态初始化就是在定义数组的同时给数组元素赋值。静态初始化使用一对大括号将初值括起来,大括号中元素的个数就是数组的长度。

格式:数据类型[] 数组名 = { ,,};

例如:int[] arr = {1,2,3};

┡ 动态初始化就是在定义数组时,只指定数组的长度,不为它赋值。在使用到的时候在给它添加元素。

格式:数据类型[] 数组名 = new 数据类型[数组长度];

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

arr[0] = 1;

arr[1] = 2;

arr[2] = 3;

数组内存图解

首先我们要先了解Java中堆和栈的概念。我们可以这样理解:

我们定义的局部变量都存储在栈中;而堆中存放的都是数组和对象(其实数组也是对象)。凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体可以有多个属性,如果一个数据消失,这个实体没有消失,还可以用,所以堆是不会释放的;但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。

下面,我们通过对一个数组的声明和初始化的例子来看内存的分配情况。

1.声明一个数组

int[] s = null;

这时,只是声明了一个数组变量,这个变量存储在栈中,堆内存中是不会发生变化的:

 

Java数据结构篇一:数组详解_第1张图片

2.给数组分配空间

s = new int[10];

当给数组分配空间以后,才会在堆内存中给数组真的分配空间,并且变量 s 会指向数组在堆内存中的地址:

 

Java数据结构篇一:数组详解_第2张图片

3.给数组元素赋值

for(int i = 0;i

s[i] = i + 1;

}

Java数据结构篇一:数组详解_第3张图片

遍历数组

遍历数组有两种方式:

┡ 普通 for 循环

for(int i = 数组第一个元素的下标; i

System.out.println(数组名[i]); // 输出下标为 i 的元素值

}

数组中的元素个数 length 是数组类中唯一的数据成员变量,使用 new 创建数组时系统自动给 length 赋值。数组一旦创建完毕,其大小就固定下来了。

┡ 增强 for 循环(JDK 1.5之后可用)

for(数组中元素的数据类型 变量名 :数组名){

System.out.println(变量名); // 输出元素值

}

多维数组

数组元素可以声明为任何类型,当数组的类型是一个一维数组类型时,这样可以建立数组的数组,即二维数组。同理,可以得到多维数组。一般来讲,n 维数组时 n-1 维数组的数组。声明多维数组时使用类型及多对方括号。以二维数组为例,定义格式如下:

类型[][] 数组名;

也可以使用如下两种方式声明一个二维数组:

类型[] 数组名[];

类型 数组名[][];

推荐使用第一种。例如:int[][] arr; 就表示一个二维数组。

多维数组的初始化

与一维数组一样,多维数组的初始化也分为静态和动态两种。

静态初始化时,在定义数组的同时为数组元素赋值。例如,二维数组 arr 的初始化如下:

int[][] arr = {, , };

这里,不必指出数组每一维的大小,系统会根据初始化时给出的初值的个数自动计算数组每一维的大小。外层括号所包含各元素是数组第一维的各元素,内层括号对应于数组第二维的元素。

对二维数组进行动态初始化时,有两种分配内存空间的方法:直接分配与按维分配。

┡ 直接分配就是直接为每一维分配空间,声明数组时,给出各维的大小。以二维数组为例,定义格式如下:

类型[][] 数组名 = new 类型[第一维数组的长度][第二维数组的长度];

例如:int[][] arr = new int[2][3]; 声明了一个2行3列的二维数组。

┡按维分配是从最高维起,分别为每一维分配内存。

创建二维数组的一般格式为:

类型[][] 数组名 = new 类型[第一维数组的长度][];

数组名[0] = new 类型[第二维数组的长度];

数组名[1] = new 类型[第二维数组的长度];

……

如果创建数组时第二维大小是一样的,则创建的是一个矩阵数组。

多维数组的访问

在定义并初始化多维数组后,可以使用多维数组中的每个元素。仍以二维数组为例,访问方式为:

数组名[第一维下标][第二维下标];

数组下标都是从 0 开始,第一维也称为行,第二维也称为列。

 

Java数据结构篇一:数组详解_第4张图片

多维数组也有length属性,但它只表示第一维数组的长度。例如:

int[][] a = new int[3][4];

a.length 的值就是 3,a[0].length 的值就是 4。

原因如下:

 

Java数据结构篇一:数组详解_第5张图片

数组对象及其引用入栈过程

在Java中,数组同样是一个对象,所以对象在内存中如何存放同样适用于数组;正如我们都知道的,java运行时数据区包括堆,JVM栈和其它。如下代码是一个小例子,那么就让我们来看看数组和它的引用在内存中是如何存放的.

class A {
    int x;
    int y;
}
...
public void m1() {
    int i = 0;
    m2();
}
public void m2() {
     A a = new A();
}
...

如上代码,让我们来调用方法m1,看看发生了什么:

当m1被调用的时候,栈帧Frame-1被创建并push到栈中,同时局部变量i也在栈帧Frame-1内创建。

然后,m2方法在m1方法内部被调用,栈帧Frame-2被创建并push到栈中,在m2方法中,一个新的对象A在堆中被创建,而它的引用则被put到栈帧Frame-2里;

现在内存中堆和栈的大致情况如下图:数组同样是对象,所以数组和对象以及引用在内存中的分布如上所示;

 

Java数据结构篇一:数组详解_第6张图片

参考文章:

https://cloud.tencent.com/developer/news/586383

https://www.cnblogs.com/ssh-html/p/9886277.html

https://www.cnblogs.com/chenpi/p/5489732.html

你可能感兴趣的:(Java基础,数据结构,数组)