news 2026/6/16 10:31:48

Java 数组详细笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 数组详细笔记

一、数组概述

数组(Array)是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。

1.1 数组的特点

  • 长度固定:数组一旦创建,大小不可改变

  • 类型相同:所有元素必须是相同数据类型

  • 有序性:元素在内存中连续存储,通过下标(索引)访问

  • 可以存储基本类型和引用类型

  • 数组本身是对象,在堆内存中分配空间

1.2 数组的分类

  • 按维度:一维数组、二维数组、多维数组

  • 按数据类型:基本数据类型数组、引用数据类型数组


二、一维数组

2.1 数组的声明

语法格式:

数据类型[] 数组名; // 推荐方式

数据类型 数组名[]; // C语言风格,不推荐

示例:

int[] scores; // 推荐

double[] prices;

String[] names;

int scores[]; // 不推荐,C语言风格

2.2 数组的创建(内存分配)

语法格式:

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

示例:

scores = new int[5]; // 创建长度为5的int数组

prices = new double[10]; // 创建长度为10的double数组

声明并创建合并写法:

int[] scores = new int[5];

String[] names = new String[3];

2.3 数组的初始化

静态初始化(指定内容,长度由系统决定)

// 完整格式 int[] scores = new int[]{100, 98, 95, 88, 90};

// 简化格式(推荐)

int[] scores = {100, 98, 95, 88, 90};

String[] names = {"张三", "李四", "王五"};

动态初始化(指定长度,元素为默认值)

int[] scores = new int[5]; // 元素默认值:0

double[] prices = new double[3]; // 元素默认值:0.0

boolean[] flags = new boolean[2]; // 元素默认值:false

String[] names = new String[4]; // 元素默认值:null

注意:不能同时指定长度和内容!错误示例:int[] arr = new int[3]{1,2,3};

2.4 数组元素的访问

通过下标/索引访问,下标从0开始,到长度-1结束

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

// 获取元素

System.out.println(arr[0]); // 输出:10

System.out.println(arr[2]); // 输出:30

// 修改元素

arr[1] = 200; System.out.println(arr[1]); // 输出:200

// 获取数组长度

System.out.println(arr.length); // 输出:5

2.5 数组的遍历

方式一:普通for循环

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

for (int i = 0; i < arr.length; i++)

{ System.out.println("第" + i + "个元素:" + arr[i]); }

方式二:增强for循环(foreach)

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

// 只能读取,不能修改

for (int num : arr) { System.out.println(num); }

foreach特点:代码简洁,但无法获取索引,只能遍历读取,不能修改元素


三、二维数组与多维数组

.1 二维数组的声明与创建

二维数组本质上是"数组的数组",可以理解为一个表格,有行和列两个维度。创建二维数组时可以同时指定行数和列数,也可以只指定行数不指定列数,这样就形成了不规则数组。

不规则数组是Java的特色功能,每行可以有不同的列数,这在某些特殊场景下非常有用,可以节省内存空间。

3.2 二维数组的初始化

静态初始化

静态初始化二维数组时,使用嵌套的大括号表示每行的元素。既可以创建规则的矩阵形式,也可以创建不规则的形式,每行的元素个数可以不同。

动态初始化

动态初始化二维数组时,指定行数和列数,所有元素自动初始化为对应类型的默认值。

3.3 二维数组的访问与遍历

二维数组需要两个下标来访问元素,第一个下标表示行号,第二个下标表示列号。

遍历二维数组需要使用双层循环,外层循环遍历行,内层循环遍历列。既可以使用普通for循环的嵌套,也可以使用增强for循环的嵌套。使用增强for循环时,外层循环的变量是一维数组类型。


四、数组常用操作

4.1 求最大值与最小值

求数组最大值的算法思路:将第一个元素作为初始最大值,然后依次与后面的每个元素比较,如果遇到更大的元素就更新最大值。求最小值的算法完全相同,只是比较方向相反。

4.2 数组求和与平均值

数组求和:初始化一个累加变量为0,遍历数组将每个元素累加到累加变量中。平均值就是总和除以数组长度,注意要进行类型转换,避免整数除法的精度丢失问题。

4.3 数组反转

数组反转的高效算法:使用对称交换的方式,只需要遍历数组的前半部分,将第i个元素与倒数第i个元素交换。这种方式的时间复杂度是O(n/2),空间复杂度是O(1),不需要额外数组空间。

4.4 数组查找

线性查找:遍历数组逐个比较,找到目标元素则返回下标,遍历完仍未找到则返回-1。线性查找的优点是数组不需要有序,缺点是平均查找效率较低。

二分查找:要求数组必须有序,每次将查找范围缩小一半,效率很高。JDK的Arrays工具类已经提供了二分查找的实现。

4.5 数组复制

数组复制有三种常用方式:

  • 手动复制:使用循环逐个元素复制,最基础但代码繁琐

  • System.arraycopy():JDK提供的本地方法,效率最高,可以指定源位置和目标位置

  • Arrays.copyOf():基于System.arraycopy()封装,使用更方便,会创建新数组

注意:直接进行引用赋值(arr1 = arr2)不是数组复制,两个引用会指向同一个数组对象,修改其中一个会影响另一个。


五、Arrays 工具类

java.util.Arrays是JDK提供的专门用于操作数组的工具类,包含大量静态方法,是数组操作的首选工具。使用前需要导入该类。

5.1 常用方法详解

  • toString():将数组转换为字符串形式,方便打印输出,是调试时最常用的方法

  • sort():对数组进行升序排序,底层使用优化的快速排序算法,效率很高

  • binarySearch():二分查找,要求数组必须有序,找到返回下标,找不到返回负数

  • fill():用指定值填充数组的全部或部分元素

  • copyOf() / copyOfRange():复制数组,可以指定新数组长度或复制范围

  • equals():比较两个数组的内容是否完全相同

  • deepToString() / deepEquals():针对多维数组的字符串转换和比较


六、数组内存分析

6.1 JVM内存区域划分

内存区域

主要作用

存储内容

栈(Stack)

方法执行的内存模型

基本数据类型变量、对象引用变量、方法参数

堆(Heap)

对象存储区域

所有new出来的对象和数组,是垃圾回收的主要区域

方法区

存储类的元信息

类信息、静态变量、常量池、方法代码

6.2 数组内存机制

数组变量存储在栈内存中,保存的是数组对象在堆内存中的地址值,而不是数组内容本身。使用new创建数组时,会在堆内存中分配连续空间,并将首地址赋值给栈中的引用变量。

当进行引用赋值时,只是将地址值复制给另一个引用变量,两个引用指向同一个堆内存中的数组对象。通过任意一个引用修改数组内容,另一个引用也会看到修改后的结果。


七、常见问题与注意事项

7.1 数组下标越界异常

这是数组操作中最常见的运行时异常。当下标小于0或者大于等于数组长度时,就会抛出此异常。编写代码时一定要注意下标的有效范围是0到length-1。

7.2 空指针异常

当数组引用变量为null时,尝试访问数组元素就会抛出空指针异常。使用数组前一定要确保数组已经正确初始化。

7.3 数组长度不可变性

数组一旦创建,长度就固定了,不能修改。length属性是只读的。如果需要改变数组大小,只能创建一个新的更大的数组,然后将原数组内容复制过去。这也是ArrayList等集合类的底层实现原理。

7.4 数组作为方法参数和返回值

数组作为方法参数时,传递的是数组的引用地址,方法内部对数组的修改会影响到原数组。数组也可以作为方法的返回值,返回的同样是数组引用。


八、数组排序算法

8.1 冒泡排序

冒泡排序是最基础的交换排序算法,核心思想是通过相邻元素的比较和交换,使较大的元素逐渐"冒泡"到数组末尾。每一轮排序都会确定一个最大元素的最终位置。

冒泡排序可以优化:如果某一轮比较中没有发生任何交换,说明数组已经有序,可以提前结束排序。

8.2 选择排序

选择排序的思路是每一轮从未排序部分选择最小的元素,放到已排序部分的末尾。选择排序的交换次数比冒泡排序少,但时间复杂度相同。

8.3 插入排序

插入排序将数组分为已排序和未排序两部分,每次从未排序部分取出第一个元素,插入到已排序部分的合适位置。插入排序在数据基本有序时效率很高。

学习总结:数组是Java中最基础也是最重要的数据结构,是学习集合框架、算法和数据结构的基础。重点掌握数组的内存机制、常用操作和Arrays工具类的使用,这些都是实际开发中每天都会用到的知识。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/16 10:30:05

【雷达】调频连续波(FMCW)合成孔径雷达(SAR)模拟器附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、程序设计科研仿真。&#x1f34e;完整代码获取 定制创新 论文复现点击&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1f3…

作者头像 李华
网站建设 2026/6/16 10:25:58

Ubuntu 22.04安装STM32CubeMX完整指南:解决依赖、配置与调试

1. 项目概述&#xff1a;为什么要在Ubuntu上安装STM32CubeMX&#xff1f; 如果你是一名嵌入式开发者&#xff0c;或者正在学习STM32单片机&#xff0c;那么STM32CubeMX这个图形化配置工具大概率是你绕不开的。它就像乐高积木的说明书&#xff0c;能帮你把复杂的时钟树、外设初…

作者头像 李华
网站建设 2026/6/16 10:22:50

操作系统页式虚存实验详解:从原理到FIFO/LRU/Clock算法实现

1. 项目概述&#xff1a;从“头歌”到页式虚存&#xff0c;一次深入内核的实践如果你正在学习操作系统&#xff0c;尤其是内存管理这一块&#xff0c;那么“页式虚存”这个概念绝对是你绕不过去的核心。最近在“头歌”这个实践平台上&#xff0c;一个名为“课堂练习4.4&#xf…

作者头像 李华
网站建设 2026/6/16 10:21:51

TinyVLM:MCU上的零样本目标检测技术解析

1. TinyVLM技术解析&#xff1a;MCU上的零样本检测革命在边缘计算领域&#xff0c;微控制器&#xff08;MCU&#xff09;因其极低的功耗和成本优势&#xff0c;成为物联网设备的首选计算平台。然而传统计算机视觉模型动辄需要数百MB内存&#xff0c;与MCU通常仅有的KB级存储资源…

作者头像 李华
网站建设 2026/6/16 10:20:09

【Kafka源码解读和使用指南】第89篇:实时数据同步平台的Kafka实战——MySQL CDC与Kafka的最佳组合

上一篇【第88篇】日志收集平台的Kafka实战——百亿日志的接入、传输与清洗 下一篇【第90篇】Kafka在微服务中的最佳实践——事件驱动架构设计全攻略 摘要 数据库里一条记录变了&#xff0c;怎么让ES、Redis、数据仓库同步感知&#xff1f;传统的定时全量同步太重了&#xff0c…

作者头像 李华