首页 > 编程笔记

Java数组的定义和使用(入门必读)

计算机将程序中需要用到的数据保存在内存中,直接通过内存地址去取值的方式很麻烦,不利于代码的开发,所以引入了变量的概念,相当于给内存起了一个别名。通过自定义的变量名就可以找到内存中存储数据的位置,进而取出其中的数据。

思考这样一个问题,如果是信息量较大的一组数据,用哪种方式保存效率更高呢?

我们当然可以创建多个变量来表示这些数据,但是很显然这种方式并不是很合理,变量个数太多不利于统一管理,并且变量的命名也会有很多限制。就好比我们管理了一间货物随意摆放、没有分门别类进行整理的超市,会是一件很苦恼的事情。程序也一样,我们应该对这种存储方式进行优化,对于超市来说就是将不同种类的货物统一摆放到对应的货架上。程序中也有具有类似功能的一种数据结构,这就是数组。

数组就是一种可以存放大量数据类型相同的变量的数据结构,是一个具有相同数据类型的数据集合。

数组中的数据必须是同一种数据类型,可以类比现实生活中学校的所有学生、机房里的所有计算机等。我们知道使用变量来保存数据,需要在内存中开辟一块空间,而数组就是在内存中开辟一串连续的空间来保存数据,如下图所示。


图 1 数组的空间是连续的

数组的基本要素

了解完数组的基本概念,接下来我们学习数组的结构。

一个数组由 4 种基本元素构成,分别是数组名称、数组元素、元素下标、数据类型。数组本身也是一个变量,既然是一个变量,就需要定义变量名,也就是数组名称。数组中保存的每一个数据都会有一个下标(从0开始),相当于编号,通过编号可以快速检索到对应的元素。数组中的所有元素必须是同一种数据类型,如下图所示。


图 2 int类型的数组

【实例】下列哪组数据可以构成一个数组?如果能,应该选择哪种数据类型?

“张三”、“李四”、true、“王五”
10.5、66、“小明”、‘男’
12、33、66、80
22.5f、33.6f、100.0f、202.2f

如何使用数组

数组也是一个变量,创建数组的步骤和创建普通变量基本一致,具体步骤如下。

1) 声明数组

数据类型[] 数组名;
如“int[] array1;”表示声明了一个 int 类型的数组,该数组中只能存放 int 类型的数据,“String[] array2;”表示声明了一个 String 类型的数组,该数组中只能存放 String 类型的数据。

2) 分配内存空间

创建数组必须要指定数组的长度,根据指定长度在内存中开辟一串连续的空间,并且长度不能修改。

语法格式如下:
数组名=new 数据类型[数组长度];
例如“array1 = new int[6];”表示 array1 的长度为 6;例如“array2 = new String[7];”表示 array2 的长度为 7。

3) 给数组赋值

分配完内存空间就可以向数组中存值了,通过下标找到数组中对应的内存空间,完成赋值,相当于通过编号找到储物柜,然后把需要保存的物品放入柜子。

例如:
array1[0] = 1;
array1[2] = 3;
array2[1] = “Java”;
array2[3] = “Hello World”;

4) 使用数组

当数组创建完成后,可以通过下标获取数组中的数据,相当于通过编号找到储物柜,然后取出柜子中保存的物品。

例如,张三身高(单位:cm)为 179,李四身高为 182,王五身高为 167,小明身高为 176,要求创建一个数组,保存 4 个用户的身高,并且求出平均值,具体实现代码如下:
public class Test {
   public static void main(String[] args) {
      int[] array;
      array = new int[4];
      array[0] = 179;
      array[1] = 182;
      array[2] = 167;
      array[3] = 176;
      //遍历数组计算平均值,数组长度可以通过length属性获取
      double sum = 0;
      for(int i = 0;i < array.length;i++){
         sum += array[i];
      }
      double avg = sum/array.length;
      System.out.println("平均身高是:"+avg);
   }
}
运行结果为:

平均身高是:176.0

上述代码可以进一步简化,声明数组和开辟空间可以用一行代码完成,代码如下所示。
public class Test {
   public static void main(String[] args) {
      int[] array = new int[4];
      array[0] = 179;
      array[1] = 182;
      array[2] = 167;
      array[3] = 176;
      //遍历数组计算平均值,数组长度可以通过length属性获取
      double sum = 0;
      for(int i = 0;i < array.length;i++){
         sum += array[i];
      }
      double avg = sum/array.length;
      System.out.println("平均身高是:"+avg);
   }
}
声明数组时,[ ]可以放在数据类型的后面,也可以放在数组名后面,即 int[] array 和 int array[] 都可以。边声明边赋值有两种方式,代码如下所示。
public class Test {
   public static void main(String[] args) {
      int[] array1 = {10,20,30};
      int[] array2 = new int[]{10,20,30};
   }
}
数组与我们之前介绍的变量在内存中的保存方式是不同的。内存可以简单分为栈内存和堆内存。基本数据类型的变量和值都保存在栈内存中,在栈内存开辟的空间中直接放入数据,比如 int num=10 在栈内存中的存储如下图所示。


图 3 num在栈内存中的存储

引用数据类型的变量保存在栈内存中。而变量的值,也就是引用实际指向的对象,保存在堆内存中,即栈内存保存的是堆内存的地址。

什么是引用数据类型?这里大家可以简单记为只要是通过 new 关键字创建的变量都是引用类型,如 String 和数组。int[] array = {50,60,70,80,90} 在内存中的存储如下图所示。


图 4 array在内存中的存储

常见错误如下:
1) 数组声明时数据类型不匹配,错误示例如下所示。
public class Test {
   public static void main(String[] args) {
      int[] array = new String[3];
   }
}
Eclipse 会提示错误信息,并给出解决方法:将 array 的类型改为 String[],保证前后一致。

2) 边声明边赋值必须写在同一行,错误示例代码如下所示。
public class Test {
   public static void main(String[] args) {
      int[] array = new int[3];
      array = {10,20,30};
      int[] array2;
      array2 = {10,20,30};
   }
}
运行代码,报错信息如下图所示。

图 5 报错信息

3) 数组下标越界,通过下标取值时给出的下标超出了数组的长度范围。这里需要注意的是,数组下标是从 0 开始的,如果数组长度为 3,下标的界限为 0~2,如果数组长度为 5,下标的界限为0~4,错误示代码如下所示。
public class Test {
   public static void main(String[] args) {
      int[] array = {10,20,30};
      System.out.println(array[3]);
   }
}
运行代码,报错信息为:


图 6 报错信息

java.lang.ArrayIndexOutOfBoundsException 表示错误原因是数组下标越界,array 的长度为 3,所以下标的界限为 0~2,3 已经超出这个范围。

数组的常用操作

在实际开发中,数组的使用非常广泛,这里给大家介绍几种最常用的操作:

1) 求数组中的最大值和最小值

求最大值和最小值的基本思路是一样的,取出数组中的第一个元素,依次与数组中的其他元素进行对比,找到目标,具体实现代码如下所示。
public class Test {
   public static void main(String[] args) {
      int[] array = {73,80,62,93,96,87};
      int max = array[0];
      for(int i = 1;i < array.length;i++){
         if(array[i] > max){
            max = array[i];
         }
      }
      System.out.println("最大值是"+max);
      int min = array[0];
      for(int i = 1;i < array.length;i++){
         if(array[i] < min){
            min = array[i];
         }
      }
      System.out.println("最小值是"+min);
   }
}
运行结果为:

最大值是96
最小值是62

2) 在数组的指定位置插入一个数据

假设现有数组 int[] array = {96,93,87,80,73,62},要求将 83 插入到下标为3的位置。

初始化数组长度为 6,现要求插入一个元素。因为数组一旦创建长度是不可改变的,所以首先需要创建一个长度为7的新数组来存储插入之后的所有元素。然后将原数组的值复制到新数组中,同时指定位置之后的元素依次向后移动一位,最后将目标元素保存到指定位置即可,如下图所示。


图 7 数组中插入数据

具体实现代码如下所示。
import java.util.Arrays;
public class Test {
   public static void main(String[] args) {
      //在数组下标为3的位置添加83
      int[] array = {96,93,87,80,73,62};
      int score = 83;
      int[] array2 = new int[array.length+1];
      for(int i = 0; i < 3; i++){
         array2[i] = array[i];
      }
      array2[3] = 83;
      for(int i = 4;i<array2.length;i++){
         array2[i] = array[i-1];
      }
      //Arrays工具类的toString方法可以将数组的元素依次取出拼接成一个字符串
      System.out.println("添加新元素之前的数组:"+Arrays.toString(array));
      System.out.println("添加新元素之后的数组:"+Arrays.toString(array2));
   }
}
运行结果如下图所示。

添加新元素之前的数组:[96,93,87,80,73,62]
添加新元素之后的数组:[96,93,87,83,80,73,62]

4) 数组排序

数组排序是指按照升序或降序对一个数组中的所有元素进行排序,实现思路是:依次比较数组中相邻的两个数字,如果是升序排列,则较大的数字放后面;如果是降序排列,则较大的数字放前面。这种方式也叫作冒泡排序,是一种常用算法,具体实现代码如下所示。
import java.util.Arrays;
public class Test {
   public static void main(String[] args) {
      int[] array = {73,80,62,93,96,87};
      //升序排列,大的放后面
      for(int j = 0; j < array.length-1;j++){
         for(int i = 0; i < array.length-1-j;i++){
            if(array[i] > array[i+1]){
               int temp = array[i];
               array[i] = array[i+1];
               array[i+1] = temp;
            }
         }
      }
      System.out.println("升序排列:"+Arrays.toString(array));
      //降序排列,小的放后面
      for(int j = 0; j < array.length-1;j++){
         for(int i = 0; i < array.length-1-j;i++){
            if(array[i] < array[i+1]){
               int temp = array[i];
               array[i] = array[i+1];
               array[i+1] = temp;
            }
         }
      }
      System.out.println("降序排列:"+Arrays.toString(array));
   }
}
运行结果为:

升序排列:[62,73,80,87,93,96]
降序排列:[96,93,87,80,73,62]

在实际开发中,对数组的各种操作并不需要开发者手写逻辑,Java 提供了一个工具类,通过调用该工具类的方法即可完成对数组的操作。这个类就是 Arrays,它保存在 java.util 包中,提供了多种操作数组的方法,可以让开发者更加快速、方便地进行开发。

例如需要对数组进行排序,我们并不需要自己写冒泡排序,直接调用 Arrays 类的方法即可完成,Arrays 类的具体使用如下所示。
import java.util.Arrays;
public class Test {
   public static void main(String[] args) {
      int[] array = {73,80,62,93,96,87};
      int[] array2 = {73,80,62,93,96,87};
      int[] array3 = {66,55,44,33,22};
      System.out.println(Arrays.equals(array, array2));
      Arrays.sort(array);
      System.out.println(Arrays.toString(array));
      Arrays.fill(array2, 66);
      System.out.println(Arrays.toString(array2));
      int[] copyArray = Arrays.copyOf(array3, 10);
      System.out.println(Arrays.toString(copyArray));
      int index = Arrays.binarySearch(array, 87);
      System.out.println(index);
   }
}
运行结果为:

true
[62, 73, 80, 87, 93, 96]
[66, 66, 66, 66, 66, 66]
[66, 55, 44, 33, 22, 0, 0, 0, 0, 0]
3

推荐阅读