Logo
Section 1 / 26

什么是数组?

本节课简要介绍数组及其类型,并讨论数组在内存中的存储方式。

导入

什么是数组?

本节课简要介绍数组及其类型,并讨论数组在内存中的存储方式。

在本节课中,我们将回顾数组的基本概念,并通过一些实际示例来掌握这种简单而强大的数据结构。

简介

数组(也称为元素的集合)是最简单且应用最广泛的数据结构。大多数数据结构(例如栈和队列)都是基于数组结构衍生而来的,因此数组被称为数据结构的核心组成部分之一。这些数据结构将在后续章节中详细讨论。数组的主要作用是将相似类型的数据组织在一起,以便快速访问。

请看下图,我们创建了一个包含四个元素的简单数组。集合中的每个项目称为数据元素,数组中存储的数据元素个数称为其大小。可以看到,除了第一个和最后一个元素外,每个数据元素最多有两个相邻元素。

...
长度为4的数组

数组索引

每个数据元素都被分配一个称为索引的数值,该数值对应于该元素在数组中的位置。需要注意的是,索引值是非负的,且始终从零开始。因此,数组的第一个元素存储在索引 0 处,最后一个元素存储在索引 size-1 处。

索引使得我们可以直接访问数组的内容。否则,若要访问某个特定元素,我们就必须遍历整个数组。这正是数组与链表之间的关键区别(链表将在下一章中介绍)。

数组的类型

数组可以存储基本数据类型的值(例如:int、char、float、boolean、byte、short、long等),也可以存储非基本数据类型的值(例如:Java对象等),甚至还可以保存其他数组的引用。根据这一点,数组可分为两类:

  • 一维数组
  • 多维数组

在基本类型数组中,值被存储在连续的内存位置中;而在非基本类型数组中,对象则被存储在堆内存区域中。

一维数组

声明和初始化一维数组的基本语法如下所示:

数组声明

在数组声明时,会创建一个数组的引用。要声明一个数组,需要指定数据类型和数组名称。

1datatype arrayName[]; 2 3或 4 5datatype[] arrayName;

示例程序

请看下面的程序:

1class OneDArray { 2 public static void main(String args[]) { 3 // 声明语法 4 int myArray1[]; 5 int[] myArray2; 6 7 } 8}

上述声明告诉编译器,引用变量 myArray1 和 myArray2 将用于指向一个 int 类型的数组。目前还没有实际的数组存在。为了将这些引用变量与真实的物理数组关联起来,我们必须使用 new 操作符创建一个数组。

数组初始化

数组初始化实际上是为数组的元素分配内存空间。初始化数组的基本语法如下:

1arrayName = new type [size];

示例程序

运行下面的程序!

1class OneDArray { 2 public static void main(String args[]) { 3 // 声明 4 int myArray[]; 5 6 // 初始化 7 myArray = new int [4]; 8 9 // 访问数组中的元素 10 for (int i = 0; i < myArray.length; i++){ 11 System.out.println(myArray[i]); 12 } 13 14 } 15}

上述程序将创建一段连续的空间,用于存储四个 int 类型的值。如果我们没有显式地指定数组元素的值,它们将被自动初始化为 0。

声明与初始化一步完成

我们也可以在一步中同时完成数组的声明和初始化。

1datatype[] arrayName = new datatype [size]; 2 3或 4 5datatype arrayName[] = new datatype [size];

示例程序

运行下面的程序并查看输出结果!

1class OneDArray { 2 public static void main(String args[]) { 3 4 // 一步完成声明与初始化 5 int[] myArray = new int [4]; 6 7 // 访问数组中的元素 8 for (int i = 0; i < myArray.length; i++){ 9 System.out.println(myArray[i]); 10 } 11 12 } 13}

向数组添加或更新元素

要向数组中添加或更新某个元素,只需指定具体的索引并赋上新值即可。

1arrayName[index] = value;

示例程序

运行下面的程序!

1class OneDArray { 2 public static void main(String args[]) { 3 4 // 一步完成声明与初始化 5 int[] myArray = new int [4]; 6 7 // 向数组中添加元素 8 myArray[0] = 10; 9 myArray[1] = 20; 10 myArray[2] = 30; 11 myArray[3] = 40; 12 13 // 访问数组中的元素 14 for (int i = 0; i < myArray.length; i++){ 15 System.out.println(myArray[i]); 16 } 17 18 // 更新索引为3的元素的值 19 myArray[3] = 900; 20 21 // 访问更新后的数组元素 22 System.out.println("更新后的数组:"); 23 for (int i = 0; i < myArray.length; i++){ 24 System.out.println(myArray[i]); 25 26 } 27 28 } 29}

注意:尝试访问超出数组范围的元素会导致 ArrayIndexOutOfBoundsException 异常。

使用数组字面量添加元素

如果数组的大小和初始值已知,我们可以使用数组字面量的方式来一次性完成数组的声明和元素的添加。

1datatype[] arrayName = {以逗号分隔的值列表};

示例程序

运行下面的程序并查看输出结果!

1class OneDArray { 2 public static void main(String args[]) { 3 4 // 一步完成声明、初始化及元素添加 5 int[] myArray = {10, 20, 30, 40}; 6 7 // 访问数组中的元素 8 for (int i = 0; i < myArray.length; i++){ 9 System.out.println(myArray[i]); 10 } 11 12 // 更新索引为3的元素的值 13 myArray[3] = 900; 14 15 // 访问更新后的数组元素 16 System.out.println("更新后的数组:"); 17 for (int i = 0; i < myArray.length; i++){ 18 System.out.println(myArray[i]); 19 20 } 21 22 } 23}

数组在内存中是如何存储的?

在 Java 中,数组是动态分配的。数组通过一个引用指针存储在内存中,该指针指向数组的第一个元素。例如,如果我们创建一个大小为 3 的数组并命名为 myArray,那么该变量将指向数组的起始位置。如下图所示:

[]

使用数组的一个主要缺点是:我们必须在实例化时指定数组的大小,这意味着数组的大小是固定的,无法扩展。如果我们想添加更多元素,就必须创建一个新的更大数组,将原数组的所有元素复制到新数组中,然后再插入新的元素。

复杂度度量

二维数组