Java 数组(Array)存储数据的“排排坐”(最新推荐)
目录
- 一、 数组到底是个啥?
- 二、 创建和使用数组 ✍️
- 2.1 声明数组引用
- 2.2 初始化数组(分配空间/赋值)
- 三、 遍历数组:挨个“点名” ♀️♂️
- 四、 数组的“常见烦恼”
- 五、 超出基础:多维数组与 Arrays工具类 ▦️
- 六、总结
- 七、练练手,检验成果!✏️
- 八、参考答案 ✅
大家好! 咱们在编程时,经常需要处理一批相同类型的数据,比如班级里所有同学的成绩 、一周每天的最高气温 ️、或者购物车里的商品列表 。如果为每个数据都声明一个单独的变量(score1
, score2
, score3
…),那代码不得写“疯&rdq编程uo;了?
这时候,就轮到 Java 中的一个基础且重要的数据结构登场了——数组 (Array)!你可以把它 想象成一排带编号的储物柜 或者一个鸡蛋托 ,专门用来整齐地存放 多个相同类型 的数据。今天,我们就来把数组这个“老朋友”彻底搞明白!
一、 数组到底是个啥?
简单来说,数组就是一个固定大小的容器 ,里面存放的元素必须是相同的数据类型。
几个关键特性要记住:
- 类型统一:一个
int
数组里只能放int
,一个String
数组里只能放String
。不能混装! - 长度固定 : 数组一旦创建,它的长度(能装多少个元素)就不能再改变了!这是数组最核心的限制之一 ⚠️。
- 连续存储 (通常): 在内存中,数组的元素通常是连续存放的,这使得通过索引访问元素非常快 ⚡️。
- 索引访问 : 每个元素都有一个唯一的索引(编号),从 0 开始!通过索引可以快速定位和访问元素。
二、 创建和使用数组 ✍️
怎么在代码里用数组呢?主要分两步:声明和初始化。
2.1 声明数组引用
告诉编译器:“我要一个能指向某种类型数组的变量”。
// 推荐的声明方式 int[] scores; String[] names; double[] prices; // C/C++ 风格的声明方式 (也能用,但不推荐) // int scores[]; // String names[];
注意:这只是声明了一个引用变量,它现在还是 null
,并没有指向任何实际的数组内存空间。
2.2 初始化数组(分配空间/赋值)
初始化才是真正创建数组对象、分配内存空间的时候。有两种主要方式:
方式一:使用 new
指定长度
这是最常用的方式,你知道需要多大的数组,但还不确定里面的具体值。
// 创建一个能存放 5 个 int 的数组 scores = new int[5]; // 分配了 5 个 int 的空间 // 创建一个能存放 10 个 String 的数组 names = new String[10]; // 分配了 10 个 String 引用的空间 // 声明和初始化可以合并 double[] salaries = new double[50];
重点: 使用 new
创建数组后,里面的元素会被自动赋予默认值:
- 数值类型 (int, double etc.):
0
或0.0
- boolean:
false
- char:
\u0000
(空字符) - 引用类型 (String, Object etc.):
null
方式二:静态初始化 (直接提供元素值)
如果你在创建数组时就已经知道里面要放哪些元素了,可以用这种更简洁的方式。编译器会根据你提供的值自动确定数组的长度。
// 直接提供初始值,长度由编译器确定 (这里是 4) int[] initialScores = {90, 85, 92, 78}; // 声明和静态初始化合并 String[] weekdays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"}; // 不能分开写!下面这php样是错误的 ❌ // int[] numbers; // numbers = {1, 2, 3}; // 编译错误 // 必须这样写: int[] numbers; numbers = new int[]{1, 2, 3}; // 或者声明时就初始化
2.3 访问数组元素:靠索引 []
数组的核心操作就是通过索引来存取元素。记住:索引从 0 开始! 非常非常重要!
public class ArrayAccess { public static void main(String[] args) { String[] fruits = {"Apple <>", "Banana <>", "Orange <>"}; // 长度为 3编程 // 访问元素 (索引 0, 1, 2) System.out.println("First fruit: " + fruits[0]); // Apple <> (索引 0) System.out.println("Second fruit: " + fruits[1]); // Banana <> (索引 1) System.out.println("Third fruit: " + fruits[2]); // Orange <> (索引 2) // 修改元素 fruits[1] = "Grape <>"; // 把第 2 个元素 (索引 1) 改成 Grape System.out.println("Second fruit now: " + fruits[1]); // Grape <> // 尝试访问不存在的索引?后果很严重! // System.out.println(fruits[3]); // 运行时错误: ArrayIndexOutOfBoundsException } }
2.4 获取数组长度:.length
属性
想知道数组能装多少东西?用 .length
属性(注意:是属性,不是方法,后面没有括号 ()
,这点和 String
的 length()
方法不同,容易混淆!)。
int[] data = new int[10]; System.out.println("Length of data array: " + data.length); // Output: 10 String[] colors = {"Red", "Green", "Blue"}; System.out.println("Number of colors: " + colors.length); // Output: 3
.length
在循环遍历数组时特别有用。
三、 遍历数组:挨个“点名” ♀️♂️
遍历数组就是按顺序访问数组中的每一个元素,通常用循环来实现。
3.1 使用传统 for
循环
最灵活的方式,因为你可以拿到当前的索引 i
。
public class ForLoopArray { public static void main(String[] args) { double[] readings = {12.5, 13.1, 11.8, 12.9}; System.out.println("Sensor Readings:"); // 循环条件通常是 i < array.length for (int i = 0; i < readings.length; i++) { System.out.println("Reading at index " + i + ": " + readings[i]); } } }
3.2 使用增强型 for
循环 (for-each)
如果不需要关心索引,只是想依次处理每个元素,这种方式更简洁、易读。
import java.util.ArrayList; // 只是为了演示集合遍历 import java.util.List; public class ForEachArray { public static void main(String[] args) { char[] vowels = {'a', 'e', 'i', 'o', 'u'}; System.out.print("Vowels: "); // 依次取出 vowels 数组中的每个 char 赋给变量 vowel for (char vowel : vowels) { System.out.print(vowel + " "); } System.out.println(); // 输出: a e i o u // 同样适用于集合 (比如 ArrayList) // List<String> names = new ArrayList<>(); ... // for (String name : names) { ... } } }
如何选择? 如果需要索引(比如要根据索引修改元素,或者需要知道当前是第几个元素),用传统 for
。如果只是读取每个元素的值,增强型 for
通常更好。
四、 数组的“常见烦恼”
使用数组时,有几个经典错误你很可能会遇到:
ArrayIndexOutOfBoundsException
<>: 这是最常见的数组错误!当你试图访问一个不存在的索引时(比如索引 < 0,或者索引 >=array.length
),就会抛出这个运行时异常。写循环时要特别小心边界条件!NullPointerException
: 如果你的数组引用变量本身是null
(即它没有指向任何数组对象),而你试图访问它的.length
属性或者通过索引访问元素(如nullArray[0]
),就会得到这个运行时异常。- 使用数组前,确保它已经被正确初始化了!长度固定不变 <>: 前面强调过,数组长度一旦确定就不能改。如果你的程序需要一个可以动态增删元素的容器,那么 Java 集合框架中的
ArrayList
等类通常是更好的选择。
五、 超出基础:多维数组与 Arrays工具类 ▦️
5.1 多维数组
你可以创建“数组的数组”,最常见的是二维数组,可以把它想象成一个表格或矩阵 ▦。
// 创建一个 3行 4列 的 int 二维数组 int[][] matrix = new int[3][4]; // 静态初始化 String[][] board = { {"X", "O", "X"}, {"O", "X", "O"}, {"X", "O", "X"} }; // 访问元素需要两个索引 matrix[0][1] = 5; // 设置第 1 行第 2 列 (索引都是从 0 开始) System.out.println("Board[1][1]: " + board[1][1]); // Output: X
遍历二维数组通常需要嵌套循环。
5.2 java.util.Arrays
工具类 <️>
Java 提供了一个非常有用的 Arrays
类(在 java.util
包下),里面包含了很多操作数组的static
方法,能省不少事:
Arrays.toString(array)
: 把数组转换成易于阅读的字符串形式,方便打印调试,强烈推荐!Arrays.sort(array)
: 对数组进行排序(原地排序)。Arrays.fill(array, value)
: 用指定值填充整个数组。Arrays.copyOf(originalArray, newLength)
: 复制原数组的一部分或全部到一个新的数组(可以用来变相“扩展”数组)。Arrays.equals(array1, array2)
: 比较两个数组的内容是否相等(注意,不是用==
比地址)。
import java.util.Arrays; // <--- 别忘了导入! public class ArraysUtilDemo { public static void main(String[] args) { int[] nums = {5, 2, 8, 1, 9}; // 好看的打印方式 System.out.println("Original array: " + Arrays.toString(nums)); // 排序 Arrays.sort(nums); System.out.println("Sorted array: " + Arrays.toString(nums)); // 填充 int[] filled = new int[5]; Arrays.fill(filled, -1); System.out.println("Filled array: " + Arrays.toString(filled)); // 复制 (取前 3 个元素) int[] copied = Arrays.copyOf(nums, 3); // nums 已经是排序后的 {1, 2, 5, 8, 9} System.out.println("Copied first 3: " + Arrays.toString(copied)); } }
六、总结
数组是 Java 中存储固定数量、相同类型元素的基础数据结构。
- 核心特性:类型统一、长度固定、索引访问 (从 0 开始)。
- 创建方式:
new Type[size]
或静态初始化{...}
。 - 访问与长度:使用
array[index]
访问,.length
获取长度。 - 遍历:常用
for
或增强for
循环。 - 常见陷阱 :
ArrayIndexOutOfBoundsException
,NullPointerException
, 长度固定限制。 - 好帮手 <️>:
java.util.Arrays
类提供了很多实用方法。
虽然 ArrayList
等集合类在灵活性上更胜一筹,但数组在性能(尤其是访问速度)和表示固定大小数据集时仍然有其优势,并且是理解集合类的基础。所以,扎实掌握数组非常重要!
七、练练手,检验成果!✏️
来,动手写写代码,巩固一下!
⭐ 基础操作 ⭐
- 声明一个可以存放 10 个
double
类型数据的数组prices
,并将其所有元素初始化为9.99
(使用循环或Arrays.fill
)。 - 创建一个
String
数组colors
,包含javascript “Red”, “Green”, “Blue”, “Yellow”。然后,修改第三个元素 (“Blue”) 为 “Purple”,并打印修改后的数组内容 (使用Arrays.toString
)。
⭐ 循环与计算 ⭐
- 给定一个
int
数组scores = {88, 92, 75, 98, 85}
,计算并打印数组中所有分数的平均值 (注意结果可能是小数)。 - 查找数组
int[] data = {5, -2, 9, 15, -8, 1}
中的最大值,并打印出来。
⭐ 概念辨析 ⭐
- 尝试解释为什么数组的索引是从 0 开始而不是从 1 开始?(提示:可以从内存地址和偏移量角度思考,或说明其历史渊源和编程习惯)
- 比较数组 (
int[]
) 和ArrayList<Integer>
的主要区别,尤其是在大小和类型方面。
八、参考答案 ✅
⭐ 基础操作答案 ⭐
1.初始化 prices
数组:
import java.util.Arrays; public class InitPrices { public static void main(String[] args) { double[] prices = new double[10]; // 方法一:使用循环 // for (int i = 0; i < prices.length; i++) { // prices[i] = 9.99; // } // 方法二:使用 Arrays.fill (更推荐) Arrays.fill(prices, 9.99); System.out.println("Initialized prices: " + Arrays.toString(prices)); } }
2.修改 colors
数组:
import java.util.Arrays; public class ModifyColors { public static void main(String[] args) { String[] colors = {"Red", "Green", "Blue", "Yellow"}; System.out.println("Original colors: " + Arrays.toString(colors)); // 第三个元素索引是 2 if (colors.length > 2) { // 做个简单检查防止越界 colors[2] = "Purple <>"; } System.out.println("Modified colors: " + Arrays.toString(colors)); // 输出: Modified colors: [Red, Green, Purple <>, Yellow] } }
⭐ 循环与计算答案 ⭐
3.计算平均分:
import java.util.Arrays; public class AverageScore { public static void main(String[] args) { int[] scores = {88, 92, 75, 98, 85}; if (scores.length == 0) { System.out.println("Array is empty, cannot calculate average."); return; } int sum = 0; for (int score : scores) { sum += score; } // 注意:为了得到精确的小数结果,需要将 sum 或 length 转为 double double average = (double) sum / scores.length; // 或者 double average = sum * 1.0 / scores.length; System.out.println("Scores: " + Arrays.toString(scores)); System.out.println("Average score: " + average); // 输出: Average score: 87.6 } }
4.查找最大值:
import java.util.Arrays; public class FindMaxValue { public static void main(String[] args) { int[] data = {5, -2, 9, 15, -8, 1}; if (data.length == 0) { System.out.println("Array is empty."); return; } int max = data[0]; // 假设第一个元素是最大值 for (int i = 1; i < data.length; i++) { if (data[i] > max) { max = data[i]; // 如果找到更大的,更新 max } } System.out.println("Data: " + Arrays.toString(data)); System.out.println("Maximum value: " + max); // 输出: Maximum value: 15 } }
⭐ 概念辨析答案 ⭐
5.为什么索引从 0 开始?
这主要是历史原因和底层实现效率的考虑。在 C 语言(Java 的重要祖先)及更早的语言中,数组名通常代表数组第一个元素在内存中的起始地址。访问数组元素 array[i]
,实际上是计算 起始地址 + i * 每个元素的大小
来找到第 i+1
个元素的地址。如果索引从 0 开始,那么访问第一个元素 array[0]
就是 起始地址 + 0 * size
,即起始地址本身,计算最简单、最高效。如果从 1 开始,访问第一个元素 array[1]
就需要计算 起始地址 + (1-1) * size
,多了一步减法。这种从 0 开始的索引(称为 zero-based indexing)已经成为 C 家族语言(包括 C++, Java, C#, javascript 等)的编程惯例。
6.int[]
vs ArrayList<Integer>
区别:
- 大小:
int[]
: 大小固定。一旦创建,长度不能改变。ArrayList<Integer>
: 大小可变。可以动态添加或删除元素,其内部容量会自动调整(虽然可能涉及性能开销)。
- 类型:
int[]
: 存储的是基本数据类型int
的值。ArrayList<Integer>
: 存储的是包装类<font color="purple">Integer</font>
的对象引用。它不能直接存储基本类型int
(但 Java 的自动装箱/拆箱机制使得使用起来很像在存取int
)。
- 功能:
ArrayList
提供了更多现成的方法(如add
,remove
,contains
,size
等),而数组功能相对基础(主要靠索引和Arrays
工具类)。 - 性能: 对于固定大小且频繁访问的场景,数组通常比
ArrayList
性能稍好(特别是对于基本类型数组,避免了装箱/拆箱开销和对象引用的开销)。
希望这篇关于数组的笔记能帮你打下坚实的基础!用熟了它,再去看集合框架就会感觉轻松很多!如果觉得有帮助,别忘了 点赞、收藏⭐、关注 哦!感谢!
到此这篇关于Java 基础--数组(Array):存储数据的www.devze.com“排排坐”的文章就介绍到这了,更多相关java数组Array内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论