Skip to content

第6章:数组

本章只讲 Java。Python/C++ 的数组和集合在末尾统一对比。

你将学会
数组创建·遍历·二维数组
前置知识
第5章 方法与栈
预计时间
30 分钟
需要准备
JDK + 编辑器
完成标志
用数组存储和处理批量数据

一个故事开头

你今天做了 5 杯奶茶:波波奶茶、杨枝甘露、柠檬茶、抹茶拿铁、红豆奶茶。

如果你用变量来记,你得写:

java
String drink1 = "波波奶茶";
String drink2 = "杨枝甘露";
String drink3 = "柠檬茶";
String drink4 = "抹茶拿铁";
String drink5 = "红豆奶茶";

如果有 100 杯呢?声明 100 个变量?先不说懒不懒,你甚至没法把"这组数据"当做一个整体来操作——比如遍历一遍算总价。

数组(Array)就是解决这个问题的——把一堆同类型的数据排成一排,编上号,用一个名字来管理。

java
String[] drinks = {"波波奶茶", "杨枝甘露", "柠檬茶", "抹茶拿铁", "红豆奶茶"};
// 编号:          0          1           2          3          4

1. 数组长什么样

java
// 声明 + 赋值一步到位
int[] scores = {85, 90, 78, 92, 88};

数组的好处是:所有元素通过编号(索引)访问,用循环遍历。

java
int[] scores = {85, 90, 78, 92, 88};
for (int i = 0; i < 5; i++) {
    System.out.println("第" + (i + 1) + "个成绩: " + scores[i]);
}

2. 创建数组的三种方式

方式1:已知所有元素

java
int[] numbers = {10, 20, 30, 40, 50};

方式2:先定长度,再逐个赋值

java
int[] numbers = new int[5];     // 创建长度为5的数组,默认值都是0
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

方式3:分开声明和赋值

java
int[] numbers;                  // 声明
numbers = new int[]{10, 20, 30}; // 赋值(不能省略 new int[])

3. 索引从 0 开始

这是新手最容易搞错的地方。Java 数组的索引从 0 开始,不是 1。

java
String[] drinks = {"波波奶茶", "杨枝甘露", "柠檬茶"};
//              索引:    0          1         2
System.out.println(drinks[0]);  // 波波奶茶
System.out.println(drinks[1]);  // 杨枝甘露
System.out.println(drinks[2]);  // 柠檬茶
System.out.println(drinks[3]);  // ❌ 数组越界!长度为 3,合法索引 0~2

💥 拆了它:数组越界

java
int[] arr = {1, 2, 3};
System.out.println(arr[3]);  // ArrayIndexOutOfBoundsException

运行结果:程序崩溃,报红色错误。Java 说:"你访问了索引 3,但这个数组只有 3 个元素(索引 0~2)。"


4. length——数组知道自己有多长

java
int[] scores = {85, 90, 78, 92, 88};
System.out.println(scores.length);  // 5

// 用 length 遍历——不用把数字写死
for (int i = 0; i < scores.length; i++) {
    System.out.println(scores[i]);
}

length 是数组的属性(不是方法,所以没有括号)。


5. 遍历数组

普通 for 循环

java
int[] scores = {85, 90, 78, 92, 88};
for (int i = 0; i < scores.length; i++) {
    System.out.println("索引 " + i + ": " + scores[i]);
}

for-each 循环(增强 for)

当你只需要元素值,不需要索引时用:

java
for (int score : scores) {
    System.out.println(score);
}

读作:"对于 scores 里的每个 int,把它赋值给 score,然后执行循环体。"

什么时候用哪种

场景用哪个
只需要元素值for-each
需要知道索引位置普通 for
要修改元素的值普通 for
倒序遍历普通 for

6. 数组的默认值

创建数组但没赋值时,Java 会给每个位置一个默认值:

类型默认值
int[]0
double[]0.0
boolean[]false
String[](及其他引用类型)null
java
int[] nums = new int[3];
System.out.println(nums[0]);  // 0
System.out.println(nums[1]);  // 0
System.out.println(nums[2]);  // 0

String[] names = new String[3];
System.out.println(names[0]);  // null

7. 数组的常见操作

找最大值

java
int[] scores = {85, 90, 78, 92, 88};
int max = scores[0];  // 假设第一个是最大的
for (int i = 1; i < scores.length; i++) {
    if (scores[i] > max) {
        max = scores[i];  // 找到更大的就更新
    }
}
System.out.println("最高分: " + max);  // 92

求和与平均

java
int sum = 0;
for (int score : scores) {
    sum += score;
}
double avg = (double) sum / scores.length;
System.out.println("平均分: " + avg);

增强型数组工具(Java 8+)

java
import java.util.Arrays;

int[] scores = {85, 90, 78, 92, 88};

Arrays.sort(scores);                 // 排序(修改原数组)
System.out.println(Arrays.toString(scores));  // 打印数组内容

int total = Arrays.stream(scores).sum();       // 求和
double average = Arrays.stream(scores).average().orElse(0);  // 平均

8. 二维数组

奶茶店有 3 家分店,每家卖了 5 杯奶茶。用二维数组存:

java
int[][] sales = {
    {15, 12, 18, 10, 14},  // 分店1:5杯的销售额
    {20, 22, 19, 15, 17},  // 分店2
    {10, 8, 14, 12, 11}    // 分店3
};

// 访问
System.out.println(sales[0][2]);  // 分店1的第3杯销售额:18
System.out.println(sales[1][4]);  // 分店2的第5杯销售额:17

// 双重循环遍历
for (int i = 0; i < sales.length; i++) {
    int storeTotal = 0;
    for (int j = 0; j < sales[i].length; j++) {
        storeTotal += sales[i][j];
    }
    System.out.println("分店" + (i + 1) + "总销售额: " + storeTotal);
}

9. 坑与注意点

数组长度不可变

java
int[] arr = new int[3];
// arr.length 永远是 3,不能扩容,不能缩容

要动态增删?后面第10章讲 ArrayList。

引用类型数组存的是引用

java
String[] names = new String[2];
names[0] = "小明";
String temp = names[0];
temp = "小张";
System.out.println(names[0]);  // 还是"小明",不是"小张"
// String 是不可变的,temp 指向了新对象,不影响原数组

for-each 不能修改数组元素

java
int[] scores = {85, 90, 78};
for (int score : scores) {
    score = 100;  // 只改了临时变量 score,没改原数组
}
System.out.println(scores[0]);  // 还是 85

要修改元素内容?用普通 for + 索引。


10. 完整例子:奶茶店日销售统计

java
import java.util.Arrays;

public class DailySales {
    public static void main(String[] args) {
        // 一天的销售记录(每杯的销售额)
        double[] sales = {15.0, 18.0, 12.0, 15.0, 16.0, 18.0, 12.0};
        
        // 计算总销售额
        double total = 0;
        for (double sale : sales) {
            total += sale;
        }
        System.out.println("今日总销售额: " + total + "元");
        
        // 计算平均单价
        double avg = total / sales.length;
        System.out.println("平均单价: " + avg + "元");
        
        // 查找最高单笔
        double max = sales[0];
        for (int i = 1; i < sales.length; i++) {
            if (sales[i] > max) {
                max = sales[i];
            }
        }
        System.out.println("最高单笔: " + max + "元");
        
        // 排序
        Arrays.sort(sales);
        System.out.println("销售额排序: " + Arrays.toString(sales));
        
        // 输出每笔超过 15 元的交易
        System.out.println("超过15元的交易:");
        for (double sale : sales) {
            if (sale > 15) {
                System.out.println("  " + sale + "元");
            }
        }
    }
}

我猜你会问

Q: 为什么数组索引从 0 开始? A: 因为数组在内存里是连续排列的,数组名就是第一个元素的地址。访问 arr[i] 相当于 地址 + i × 元素大小。从 0 开始计算更高效(省一次减法)。

Q: 数组和后面要学的 ArrayList 有什么区别? A: 数组定长,ArrayList 自动扩容。日常用 ArrayList 更多,但在性能敏感的场景(几百万数据)数组更快。


你现在学会的东西

  1. 数组 = 同类型数据排成一排,用索引(从 0 开始)访问
  2. 创建方式三种{值列表}new int[长度]new int[]{值列表}
  3. length 告诉你数组多长,遍历时用它,别写死数字
  4. for-each 遍历更简洁,但不能改元素内容
  5. 数组越界 = 程序崩溃ArrayIndexOutOfBoundsException
  6. 数组长度不可变——需要变长容器?学完数组学 ArrayList

✅ 验收标准

完成本章后,你应该能:

  • [ ] 用三种方式创建数组并初始化
  • [ ] 用索引读写数组元素
  • [ ] 用 for-each 遍历数组
  • [ ] 声明和遍历二维数组
  • [ ] 写出数组求最大/求和等常用操作

📌 常见卡点

  • 数组索引从 0 开始——最后一个元素的索引是 length-1
  • 数组越界——访问不存在的索引抛出 ArrayIndexOutOfBoundsException
  • 数组长度固定——创建后不能增删元素
  • 数组变量是引用——赋值是传引用,不是复制

🔜 现在不需要理解

  • 多维数组的底层存储布局
  • Arrays 工具类的所有方法——用到时查表
  • 数组的反射操作——高级话题


🧪 练习

1. 声明数组:声明一个 double[] prices = {12.5, 15.0, 18.0, 10.0},用 for 循环计算总价。

2. 找最大值和最小值:有一个 int[] numbers = {34, 78, 12, 90, 45, 67},找出最大值和最小值。

3. 数组反转:声明 int[] arr = {1, 2, 3, 4, 5},写一个循环把它反转为 {5, 4, 3, 2, 1}。(提示:交换首尾对应的元素)


下一篇

第7章 面向对象(上):类与对象

用 ❤️ 构建 | Software Systems Atlas