Java 入门(四):数组——数据的集合管理

1. 引言

前几篇已经搞定环境、变量和流程控制,这篇来说数组。为什么需要它?举个例子:班上有 50 个同学,想把每个人的成绩都存下来,如果还是一个个声明变量,就得写 score1score50,再往后 100 个、1000 个怎么办?这种时候变量明显不够用了。

数组就是来解决这类问题的:一个变量就能装下一批同类型的数据。下面从声明、初始化、遍历,再到几个常用操作,逐个过一遍。

2. 什么是数组

数组可以理解成一批同类型数据的容器。拿储物柜类比:柜子规格都一样,每个柜子有唯一的编号,按编号就能找到对应的东西。

它有几个特点:

  • 类型固定 :一个数组里只能装同一种类型的数据,要么全是 int,要么全是 String
  • 长度固定 :创建时多长就是多长,后面改不了;想动态扩容,得用 ArrayList 这类集合。
  • 索引从 0 开始 :第一个元素的下标是 0,最后一个是 长度 - 1
  • 内存连续:元素在内存里挨着放,所以按下标访问速度很快。

3. 数组的声明与初始化

用数组分两步:先声明,再初始化(分配空间并赋值)。

3.1 声明数组

声明有两种写法,推荐第一种:

java 复制代码
// 推荐写法:数据类型[] 数组名;
int[] scores;
String[] names;

// 兼容 C/C++ 风格的写法:数据类型 数组名[];
int scores2[];

3.2 初始化数组

初始化有三种方式。

方式一:动态初始化------只指定长度,元素使用默认值

java 复制代码
int[] scores = new int[5]; // 创建一个长度为 5 的 int 数组

此时数组中的 5 个元素会被自动赋予默认值。不同类型的默认值如下:

数据类型 默认值
int / short / byte / long 0
double / float 0.0
char '\\u0000'(空字符)
boolean false
引用类型(如 String null

方式二:静态初始化------声明的同时直接赋值

java 复制代码
int[] scores = {88, 92, 75, 100, 60};
String[] names = {"张三", "李四", "王五"};

方式三:先声明,后静态初始化(注意:此时不能省略 new)

java 复制代码
int[] scores;
scores = new int[]{88, 92, 75, 100, 60};

下面这种写法会编译报错,因为只有声明的同时才能省略 new int[]

java 复制代码
int[] scores;
scores = {88, 92, 75}; // 编译错误!

4. 访问与修改数组元素

数组通过索引访问,写法是 数组名[索引]

java 复制代码
public class ArrayAccessDemo {
    public static void main(String[] args) {
        int[] scores = {88, 92, 75, 100, 60};

        // 读取第一个元素(索引为 0)
        System.out.println("第一名同学的成绩:" + scores[0]);

        // 修改第三个元素(索引为 2)
        scores[2] = 80;
        System.out.println("修改后第三名同学的成绩:" + scores[2]);

        // 获取数组长度
        System.out.println("数组长度:" + scores.length);
    }
}

运行结果:

text 复制代码
第一名同学的成绩:88
修改后第三名同学的成绩:80
数组长度:5

提示:数组名.length 用来获取数组长度,它是属性不是方法,后面不要加括号。

4.1 数组越界异常

如果索引跑到 0 ~ length-1 范围之外,就会抛 ArrayIndexOutOfBoundsException

java 复制代码
int[] scores = {88, 92, 75};
System.out.println(scores[3]); // 运行时报错:索引越界

这个错误新手经常踩,取值前记得先确认索引范围。

5. 遍历数组

遍历就是把数组里的元素一个个取出来。上一篇文章学的循环这里都用得上,常见有三种写法。

5.1 使用普通 for 循环

java 复制代码
public class ArrayTraversalDemo {
    public static void main(String[] args) {
        int[] scores = {88, 92, 75, 100, 60};

        for (int i = 0; i < scores.length; i++) {
            System.out.println("第 " + (i + 1) + " 名同学的成绩:" + scores[i]);
        }
    }
}

5.2 使用增强 for 循环(for-each)

Java 5 之后多了增强 for 循环,写起来更省事,适合只读遍历:

java 复制代码
for (int score : scores) {
    System.out.println("成绩:" + score);
}

注意,这里拿到的 score 只是副本,改它不会影响原数组:

java 复制代码
for (int score : scores) {
    score = 0;          // 只修改了副本,原数组不变
}
System.out.println(scores[0]); // 仍然输出 88

如果要在遍历时改元素,还是用普通 for 循环带下标比较靠谱。

6. 数组的常见操作

下面这几个是平时写数组最常碰到的处理逻辑,都敲一遍以后就熟了。

6.1 求最值

java 复制代码
public class ArrayMaxDemo {
    public static void main(String[] args) {
        int[] scores = {88, 92, 75, 100, 60};

        int max = scores[0]; // 假设第一个元素是最大值
        for (int i = 1; i < scores.length; i++) {
            if (scores[i] > max) {
                max = scores[i];
            }
        }
        System.out.println("最高分:" + max);
    }
}

6.2 求和与平均值

java 复制代码
public class ArrayAverageDemo {
    public static void main(String[] args) {
        int[] scores = {88, 92, 75, 100, 60};

        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        double average = (double) sum / scores.length;
        System.out.println("总分:" + sum);
        System.out.printf("平均分:%.2f%n", average);
    }
}

6.3 数组反转

java 复制代码
public class ArrayReverseDemo {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};

        for (int left = 0, right = arr.length - 1; left < right; left++, right--) {
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }

        // 输出反转结果
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

运行结果:

text 复制代码
5 4 3 2 1

6.4 冒泡排序

排序在面试和比赛里经常碰到,先看最经典的冒泡排序:

java 复制代码
public class BubbleSortDemo {
    public static void main(String[] args) {
        int[] arr = {64, 34, 25, 12, 22, 11, 90};

        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }

        System.out.print("排序结果:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

运行结果:

text 复制代码
排序结果:11 12 22 25 34 64 90

7. 二维数组

前面的数组都是一维的,像一条线。二维数组可以看成"数组的数组",更像一张表格,有行有列。

7.1 二维数组的初始化

java 复制代码
// 静态初始化:3 行 3 列的矩阵
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 动态初始化:3 行 4 列,每个元素默认值为 0
int[][] grid = new int[3][4];

7.2 遍历二维数组

java 复制代码
public class TwoDimensionalArrayDemo {
    public static void main(String[] args) {
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println(); // 每行输出后换行
        }
    }
}

运行结果:

text 复制代码
1 2 3
4 5 6
7 8 9

补充:Java 的二维数组每一行列数可以不一样,这叫"不规则数组"。比如 int[][] triangle = {``{1}, {2, 3}, {4, 5, 6}}; 就是个三角形结构。

8. 实战练习

做完下面几题,这篇的内容基本就上手了:

  1. 成绩统计 :创建一个长度为 10 的 int 数组,随机存入 0~100 之间的成绩,统计最高分、最低分和平均分。
  2. 元素查找 :在数组 {12, 45, 67, 89, 34, 23} 中查找某个数字是否存在,若存在则输出其索引。
  3. 数组去重 :给定数组 {1, 3, 2, 3, 5, 1, 4},输出其中不重复的元素。
  4. 矩阵对角线求和:给定一个 3×3 的二维数组,计算主对角线(左上到右下)元素之和。

9. 数组的局限与下一步

数组最大的问题是长度写死。程序跑起来以后想随时增删元素,它就不太好使;而且像插入、删除、查找这些常用操作,都得自己写。

集合框架里的 ArrayListHashMap 解决了这些问题:支持动态扩容,还自带不少方法。不过数组是更底层的东西,先把数组弄明白,后面学集合和算法会轻松很多。

下一篇看 Java 里的方法(函数),把重复的代码封装起来。

10. 总结

这篇的内容,一句话概括:数组用来存一批同类型数据,长度固定、索引从 0 开始;初始化分动态和静态;访问用 数组名[索引],长度用 length;遍历时普通 for 适合边改边读,增强 for 适合只读;常用操作练了最值、求和、反转、冒泡排序;二维数组就是"数组的数组"。

原理本身不难,关键还是动手敲。练习没做完的话回去补上,比只看一遍有用得多。

相关推荐
Lambert2812 小时前
AgentScope Java 从零(07):官方有权限引擎,我却在工具里写了个 if
java·后端·ai编程
Kyrie_kk2 小时前
Java--ThreadLocal线程副本(一)
java·后端
Y3815326623 小时前
SERP 数据清洗实战:字段标准化、日期解析与去重键
开发语言·数据库·python·python数据库
君顾13 小时前
本地城市低空经济管理系统定制:城市级低空运营平台架构与落地实战
java·开发语言·飞手
奈斯先生Vector3 小时前
当模型版本不断变化,RelayRouter 能否帮助 AI 应用摆脱深度绑定
android·java·人工智能·开源·aigc
用户8181870627463 小时前
第28章 消息积压应急处理实录:一次真实大促故障复盘
java·后端
宸津-代码粉碎机4 小时前
微服务线上踩坑复盘:接口超时、负载倾斜隐形问题根治方案(生产级配置)
java·大数据·人工智能·python·spring
多多鼠4 小时前
System Prompt 的“版本漂移”问题:从变更管理到 A/B 测试体系
开发语言·网络·人工智能·python·langchain
LuTshoes4 小时前
spring ai 实战RAG(4)-模块化RAG
java·人工智能·spring