2.7 数组

 思维导图:

2.7.1 数组的基本要素

### 2.7 数组

数组在编程中是一种重要的数据结构,用于存储一系列的数据。特别是当处理大量相似类型的数据时,数组的效用尤为显著。

#### 2.7.1 数组的基本要素

一个数组主要由以下四个基本元素构成:

1. **数组名称**:用于标识数组的唯一标识。
2. **数组元素**:存储在数组中的数据。
3. **元素索引**:表示数组元素位置的数字。在Java中,索引始于0。
4. **数据类型**:数组中存储的所有元素的数据类型。

在Java中声明一个数组的基本格式如下:

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

例如,要声明一个可以存储100个整数的数组,可以这样写:

int[] x;
x = new int[100];

这样的声明方式意味着在内存中为`x`分配了100个连续的整数存储空间。默认情况下,这100个整数的初值都是0。

#### 2.7.2 数组在内存中的表示

当声明一个数组变量(例如上面的`x`)时,实际上创建了一个指向数组的引用。这个引用本身也是存储在内存中的。当使用`new`关键字实际创建数组时,会在内存中为该数组分配相应的空间。

考虑上面的例子,首先声明了一个数组引用`x`,它的初始状态如图2-39所示。接着,为它分配100个整数的存储空间。此时,`x`的状态如图2-40所示,它指向这100个整数的首地址。

要访问数组中的元素,可以使用如`x[0]`、`x[1]`...的方式。这里的数字称为数组的索引或下标。重要的是要记住,数组的索引始于0,所以一个长度为100的数组的最后一个元素的索引是99。

为了方便获取数组的长度,Java提供了一个名为`length`的属性。可以通过`数组名.length`的方式来获得。

#### 小结

使用数组可以简化存储和处理大量数据的复杂性。通过上面的知识,我们知道了如何在Java中声明、初始化和访问数组,以及如何获取数组的长度。这为后续的数组操作和处理提供了基础。

 2.7.2 数组的简单使用

### 2.7.2 数组的简单使用

数组在Java中的使用是相当直观和简单的。下面我们通过一个示例来了解如何定义、初始化和访问数组。

#### 示例:Example22.java

public class Example22 {
    public static void main(String[] args) {
        // 声明数组变量
        int[] arr;
        
        // 创建数组对象并分配空间
        arr = new int[3];
        
        // 访问数组中的各个元素
        System.out.println("arr[0] = " + arr[0]);
        System.out.println("arr[1] = " + arr[1]);
        System.out.println("arr[2] = " + arr[2]);
        
        // 打印数组的长度
        System.out.println("数组的长度是:" + arr.length);
    }
}

在上述代码中,`arr`是一个整数类型的数组。它首先被声明,然后创建了一个长度为3的整数数组。随后,程序访问数组的每个元素并打印其值。最后,我们打印了数组的长度。

注意,在这个示例中,我们没有为数组的元素显式地赋值。所以,当我们尝试访问数组中的元素时,它们都显示为默认值0(对于整数数组来说)。

#### 结果

运行这段代码会得到以下的输出:

arr[0] = 0
arr[1] = 0
arr[2] = 0
数组的长度是:3

这里要注意的是,当我们声明并初始化一个新的数组但没有为它的元素分配值时,Java会为数组中的每个元素提供一个默认值。对于基本数据类型,如整数,默认值是0。对于对象,如String,默认值是null。

#### 小结

通过这个简单的例子,我们了解了如何在Java中声明、初始化和访问数组。使用数组,我们可以轻松地存储和操作大量数据,这对于编程中的许多任务来说都是非常有用的。

### 2:7.2 数组的简单使用

**1. 定义数组**

数组是一个容器,可以存储多个相同类型的元素。数组中每个元素都有一个自动编号,也叫做索引或下标,最小索引是0,最大索引是数组长度减1。

- **动态初始化**: 仅定义数组长度,系统会为数组元素自动赋初值。

  int[] arr = new int[3];

- **静态初始化**: 定义数组的时候同时为数组元素赋值。
 

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

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

**注意**: 第二种静态初始化方式更为简洁。

**2. 访问数组元素**

可以通过数组名加索引的方式访问数组元素。

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

**3. 数组的属性**

 System.out.println("数组的长度是:" + arr.length);

**4. 默认初始化值**

不同的数据类型的数组元素,系统赋予的默认值不同:

数据类型默认值
byte、short、int、long0
float、double0.0
char一个空字符,即`\u0000`
boolean false  
引用数据类型 null

**5. 赋值**

除了使用默认值外,也可以显式地为数组的每个元素赋值。

arr[0] = 1;
arr[1] = 2;

**6. 注意事项**

- 当访问数组的元素时,索引不能超出0~length-1的范围,否则会出现索引越界的错误。
- 静态初始化时,不能同时指定数组的长度和为数组的元素赋值,如`int[]arr =new int[4]{1,2,3,4}`,这样的写法是错误的。

**示例**: 

文件`Example22.java`展示了如何定义一个整数类型的数组,给数组的元素赋值以及访问数组的元素。
文件`Example24.java`展示了数组的静态初始化方式。
文件`Example25.java`尝试访问一个超出范围的数组索引,会导致运行时异常。

2.7.3 数组的常见操作

### 2.7.3 数组的常见操作

数组在编程中的应用极为广泛。对数组的操作不仅仅局限于声明、初始化和简单的数据访问,还包括更复杂的遍历、搜索、排序和插入等操作。

**1. 数组的遍历**

- 为了访问数组中的每一个元素,我们经常会使用循环结构进行遍历。`for`循环是常用的遍历手段。例如:

int[] arr = {1, 2, 3, 4, 5};
for(int i = 0; i < arr.length; i++){
    System.out.println(arr[i]);
}

**2. 异常操作**

- **数组越界异常**:在尝试访问数组的一个不存在的索引时,会触发`ArrayIndexOutOfBoundsException`。如在长度为4的数组中尝试访问索引4。

- **空指针异常**:当一个数组引用被设置为`null`(意味着它不再引用任何数组对象)后,再试图通过这个引用访问数组的元素,会引发`NullPointerException`。

**示例**:

在文件`Example26.java`中,我们首先创建了一个大小为3的数组,并为其第一个元素赋了值。在访问该数组的元素后,我们将数组的引用置为`null`,然后再次尝试访问数组的元素,结果就是一个`NullPointerException`。

int[] arr = new int[3];   //定义一个长度为3的数组
arr[0] = 5;               //为数组的第一个元素赋值
System.out.println("arr[0]=" + arr[0]);  //访问数组的元素
arr = null;              //将变量arr置为null
System.out.println("arr[0]=" + arr[0]);  //再次访问数组的元素时会引发空指针异常

在处理数组时,为避免此类异常,建议:
1. 时刻检查数组的边界。
2. 在使用数组引用前进行非空检查。

**小结**: 数组是Java中的基础数据结构,熟练掌握其操作和相关注意事项是每个Java程序员的必备技能。

## 2.7.3 数组的常见操作

**简介**:
数组是Java中最基本的数据结构之一,用于存储同一类型的多个元素。以下是对数组进行的一些常见操作。

### 1. 数组的遍历

**定义**:  
遍历是一种基本操作,它允许我们访问数组中的每一个元素。

**示例**:  

public class Example27 {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

- 注意:数组的索引范围是0到数组长度减1。

### 2. 数组中最值的获取

**定义**:  
这涉及到在数组中查找最大或最小值。

**示例**:  

public class Example28 {
    public static void main(String[] args) {
        int[] arr = {4, 1, 6, 3, 9, 8};
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        System.out.println("数组arr中的最大值为:" + max);
    }
}

### 3. 在数组的指定位置插入一个数据

**定义**:  
因为数组的大小是固定的,所以在插入新的数据时,我们需要创建一个新的更大的数组,然后将旧数组的数据复制到新数组中。**示例**:  

 

public class Example29 {
    public static void main(String[] args) {
        int[] arr = {10, 11, 13, 14, 15};
        int score = 12;
        int[] arr2 = new int[arr.length + 1];
        
        for (int i = 0; i < 3; i++) {
            arr2[i] = arr[i];
        }
        arr2[2] = score;
        for (int i = 3; i < arr2.length; i++) {
            arr2[i] = arr[i-1];
        }

        System.out.print("添加新元素之前的arr数组:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + ",");
        }
        System.out.println("");

        System.out.print("添加新元素之后的arr2数组:");
        for (int i = 0; i < arr2.length; i++) {
            System.out.print(arr2[i] + ",");
        }
    }
}


这些是对数组进行的几种基本操作,对于复杂的操作和算法,可能需要使用其他数据结构或Java提供的工具类。

**4.数组排序**

**冒泡排序简介**:

在日常编程开发中,排序是数组中最常用的操作。Java提供了多种数组排序算法,其中一种常见的是冒泡排序。

冒泡排序的基本思想是:通过不断地比较相邻元素的大小,使小的数像“气泡”一样“浮”到上面,而大的数则“沉”到下面。这个过程类似于气泡在水中不断上浮的过程。

**冒泡排序步骤分析**:

1. **第一步**:从第一个元素开始,对每对相邻的元素进行比较。如果前一个元素大于后一个元素,则交换它们的位置。完成这一轮后,最大的元素会被放在数组的最后一个位置。

2. **第二步**:忽略最后一个元素,再次对剩下的元素进行两两比较,把第二大的元素放在倒数第二的位置。

3. **第三步**:这样一直继续,直到没有元素需要比较为止。

**Java代码示例**:

文件名:`Example30.java`

public class Example30 {
    public static void main(String[] args) {
        int[] arr = {9, 8, 3, 5, 2};

        // 冒泡排序前,打印数组元素
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();

        // 开始冒泡排序
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 交换两个元素
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }

        // 冒泡排序后,打印数组元素
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

**两个元素的交换**:数组中两个元素的交换过程在上述代码中的第16至18行。具体步骤如下:

1. 使用临时变量`temp`保存一个元素的值。
2. 将另一个元素的值赋给第一个元素。
3. 最后,将临时变量`temp`的值赋给第二个元素。

这样,两个元素的值就交换了位置。

**总结**:

冒泡排序是排序算法中的基础算法之一,它的原理简单、容易实现,但在大规模数据中的效率不如其他高级排序算法。在学习数据结构和算法时,了解并掌握冒泡排序是非常必要的。

2.7.4 二维数组

# 2.7.4 二维数组

## 介绍

在程序中,仅使用一维数组是远远不够的。例如,统计一个学校各个班级的学生成绩,需要同时标识班级和学生成绩,此时使用一维数组是不足够的。为此,多维数组被引入,它可以简单地理解为数组中的数组。其中,二维数组是最常见的,它具有两个索引,用于表示行和列。

## 定义

二维数组可以用多种方式定义,以下介绍三种常见方法:

1. **固定行和列的二维数组**  
```java
数据类型[][] 数组名 = new 数据类型[行数][列数];
```
例如:
```java
int[][] xx = new int[3][4];
```
这会创建一个3行4列的二维数组。

2. **确定行数,但列数不确定的二维数组**  
```java
数据类型[][] 数组名 = new 数据类型[行数][];
```
例如:
```java
int[][] xx = new int[3][];
```

3. **使用具体的元素值来定义二维数组**  
```java
数据类型[][] 数组名 = {{第0行元素}, {第1行元素}, ..., {第n行元素}};
```
例如:
```java
int[][] xx = {{1, 2}, {3, 4, 5, 6}, {7, 8, 9}};
```

## 访问元素

要访问二维数组中的某个元素,使用以下格式:
```java
数组名[行索引][列索引]
```
例如,访问`xx`数组的第一个元素的第二个值:
```java
xx[0][1];
```

## 示例

以下示例展示了如何使用二维数组统计一个公司3个销售小组的销售额:

public class Example31 {
    public static void main(String[] args) {
        //定义一个长度为3的二维数组
        int[][] arr = new int[3][];
        //为数组的元素赋值
        arr[0] = new int[]{11, 12};
        arr[1] = new int[]{21, 22, 23};
        arr[2] = new int[]{31, 32, 33, 34};
        //定义变量记录公司总销售额
        int sum = 0;
        //遍历数组元素
        for (int i = 0; i < arr.length; i++) {
            int groupSum = 0;  //小组销售额
            for (int j = 0; j < arr[i].length; j++) {
                groupSum += arr[i][j];
            }
            sum += groupSum; //累加小组销售额到总销售额
            System.out.println("第" + (i + 1) + "小组销售额为:" + groupSum + "万元。");
        }
        System.out.println("总销售额为:" + sum + "万元。");
    }
}

## 总结

二维数组是一个强大的数据结构,它为存储和管理表格形式的数据提供了方便。在Java中,可以使用多种方式来定义和初始化它们,并通过行和列索引来访问其元素。

总结:

以下是关于Java中数组的总结:

### 重点:
1. **数组的定义与初始化**:Java中的数组是一个引用数据类型,可以存储多个同类型的数据。可以通过静态初始化和动态初始化进行定义和赋值。
   
2. **二维数组**:在Java中,可以有多维数组,但最常用的是二维数组。理解它如何工作,特别是如何通过两个索引来访问元素,是至关重要的。
   
3. **数组的属性**:每个数组都有一个属性`length`,代表数组的长度。

### 难点:
1. **多维数组**:理解和操作多维数组可能需要时间。尤其是在内部循环中使用多维数组可能会使一些初学者感到困惑。

2. **数组的内存表示**:理解数组是如何在内存中存储的,以及如何与数组引用和实际的数组对象进行交互,可以帮助更深入地理解Java中的数组。

3. **数组的边界**:在处理数组时,超出其边界是一个常见的错误。

### 易错点:
1. **越界访问**:尝试访问数组的非法索引(通常小于0或大于等于`length`)会导致`ArrayIndexOutOfBoundsException`。

2. **空引用访问**:未初始化的数组引用可能导致`NullPointerException`。

3. **误解数组长度**:常常与新手混淆的是,`array.length`给出的是数组的长度,而不是最后一个元素的索引。

### 使用技巧:
1. **增强型for循环**:使用增强型for循环(也称为“for-each”循环)可以更简洁地遍历数组。

   ```java
   for(int value : array) {
       System.out.println(value);
   }
   ```

2. **工具类**:Java的`Arrays`类提供了许多有用的数组操作方法,如`sort()`, `toString()`, `fill()`, `binarySearch()`等。

3. **数组拷贝**:可以使用`System.arraycopy()`或`Arrays.copyOf()`来复制数组。

4. **变长参数**:当定义方法时,可以使用变长参数来接受任意数量的参数。这实际上是一个数组,可以在方法体内像数组一样使用它。

总之,Java中的数组是一个强大的数据结构,但也需要注意边界和空引用问题。通过理解它们如何在内部工作,以及使用Java提供的工具和技巧,可以更有效地使用数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏驰和徐策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值