Appearance
数组
数组是一种容器,可以存储多个相同类型的数据。数组在内存中是连续存储的,通过索引可以快速访问元素。
数组概述
text
┌─────────────────────────────────────────────────────────────────┐
│ 数组特点 │
├─────────────────────────────────────────────────────────────────┤
│ 1. 长度固定:创建后长度不可改变 │
│ 2. 类型统一:只能存储同一种数据类型 │
│ 3. 连续存储:内存中连续分配空间 │
│ 4. 索引访问:从 0 开始,最大索引为 length-1 │
│ 5. 引用类型:数组本身是引用类型 │
└─────────────────────────────────────────────────────────────────┘一维数组
数组声明和初始化
java
public class ArrayDeclaration {
public static void main(String[] args) {
// 方式一:先声明,后初始化
int[] arr1;
arr1 = new int[5]; // 创建长度为 5 的数组
// 方式二:声明时初始化
int[] arr2 = new int[5];
// 方式三:静态初始化(指定元素)
int[] arr3 = {1, 2, 3, 4, 5};
// 方式四:静态初始化的完整形式
int[] arr4 = new int[]{1, 2, 3, 4, 5};
// 字符串数组
String[] names = {"张三", "李四", "王五"};
// 访问数组元素
System.out.println("arr3[0] = " + arr3[0]); // 1
System.out.println("arr3[4] = " + arr3[4]); // 5
// 数组长度
System.out.println("arr3.length = " + arr3.length); // 5
// 修改数组元素
arr3[0] = 100;
System.out.println("修改后 arr3[0] = " + arr3[0]); // 100
}
}数组的内存结构
text
┌─────────────────────────────────────────────────────────────────┐
│ 数组内存结构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 栈内存 堆内存 │
│ ┌─────────┐ ┌───────────────────────────┐ │
│ │ arr │─────────────>│ [0] [1] [2] [3] [4] │ │
│ │ (引用) │ │ 1 2 3 4 5 │ │
│ └─────────┘ └───────────────────────────┘ │
│ new int[]{1,2,3,4,5} │
│ │
│ 数组变量存储的是数组对象的地址(引用) │
│ 数组对象存储在堆内存中 │
└─────────────────────────────────────────────────────────────────┘数组遍历
java
public class ArrayTraversal {
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
// 方式一:普通 for 循环
System.out.println("普通 for 循环:");
for (int i = 0; i < arr.length; i++) {
System.out.println("arr[" + i + "] = " + arr[i]);
}
// 方式二:增强 for 循环(for-each)
System.out.println("\n增强 for 循环:");
for (int num : arr) {
System.out.println("元素: " + num);
}
// 方式三:使用 Arrays 工具类
System.out.println("\nArrays.toString:");
System.out.println(java.util.Arrays.toString(arr));
// 带索引的遍历
System.out.println("\n带索引遍历:");
int index = 0;
for (int num : arr) {
System.out.println("arr[" + index + "] = " + num);
index++;
}
}
}数组操作示例
java
public class ArrayOperations {
public static void main(String[] args) {
int[] arr = {64, 34, 25, 12, 22, 11, 90};
// 求最大值
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println("最大值: " + max);
// 求最小值
int min = arr[0];
for (int num : arr) {
if (num < min) {
min = num;
}
}
System.out.println("最小值: " + min);
// 求和与平均值
int sum = 0;
for (int num : arr) {
sum += num;
}
double avg = (double) sum / arr.length;
System.out.println("总和: " + sum);
System.out.println("平均值: " + avg);
// 查找元素
int target = 25;
int index = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
index = i;
break;
}
}
System.out.println("元素 " + target + " 的索引: " + index);
// 统计元素出现次数
int[] counts = {1, 2, 3, 2, 1, 2, 3, 3, 3};
int targetNum = 3;
int count = 0;
for (int num : counts) {
if (num == targetNum) {
count++;
}
}
System.out.println(targetNum + " 出现的次数: " + count);
}
}数组排序
java
import java.util.Arrays;
public class ArraySort {
public static void main(String[] args) {
int[] arr = {64, 34, 25, 12, 22, 11, 90};
// 使用 Arrays.sort() 排序
System.out.println("排序前: " + Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("排序后: " + Arrays.toString(arr));
// 冒泡排序(手动实现)
int[] arr2 = {64, 34, 25, 12, 22, 11, 90};
System.out.println("\n冒泡排序:");
for (int i = 0; i < arr2.length - 1; i++) {
for (int j = 0; j < arr2.length - 1 - i; j++) {
if (arr2[j] > arr2[j + 1]) {
// 交换元素
int temp = arr2[j];
arr2[j] = arr2[j + 1];
arr2[j + 1] = temp;
}
}
}
System.out.println("排序后: " + Arrays.toString(arr2));
// 选择排序
int[] arr3 = {64, 34, 25, 12, 22, 11, 90};
System.out.println("\n选择排序:");
for (int i = 0; i < arr3.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr3.length; j++) {
if (arr3[j] < arr3[minIndex]) {
minIndex = j;
}
}
// 交换
int temp = arr3[i];
arr3[i] = arr3[minIndex];
arr3[minIndex] = temp;
}
System.out.println("排序后: " + Arrays.toString(arr3));
}
}多维数组
二维数组
二维数组可以看作是一维数组的数组,常用于表示矩阵或表格数据。
java
public class TwoDimensionalArray {
public static void main(String[] args) {
// 声明和初始化
// 方式一:先声明后初始化
int[][] matrix1;
matrix1 = new int[3][4]; // 3行4列
// 方式二:声明时初始化
int[][] matrix2 = new int[3][4];
// 方式三:静态初始化
int[][] matrix3 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 访问元素
System.out.println("matrix3[0][0] = " + matrix3[0][0]); // 1
System.out.println("matrix3[1][2] = " + matrix3[1][2]); // 6
// 获取行数和列数
System.out.println("行数: " + matrix3.length); // 3
System.out.println("第0行列数: " + matrix3[0].length); // 3
// 遍历二维数组
System.out.println("\n遍历二维数组:");
for (int i = 0; i < matrix3.length; i++) {
for (int j = 0; j < matrix3[i].length; j++) {
System.out.print(matrix3[i][j] + " ");
}
System.out.println();
}
// 使用增强 for 循环遍历
System.out.println("\n增强 for 循环遍历:");
for (int[] row : matrix3) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
}
}不规则二维数组
java
public class IrregularArray {
public static void main(String[] args) {
// 不规则数组:每行的列数可以不同
int[][] irregular = new int[3][];
// 为每行分配不同的列数
irregular[0] = new int[2]; // 第0行有2列
irregular[1] = new int[3]; // 第1行有3列
irregular[2] = new int[4]; // 第2行有4列
// 初始化
int value = 1;
for (int i = 0; i < irregular.length; i++) {
for (int j = 0; j < irregular[i].length; j++) {
irregular[i][j] = value++;
}
}
// 打印
System.out.println("不规则二维数组:");
for (int[] row : irregular) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
// 使用静态初始化创建不规则数组
int[][] triangle = {
{1},
{2, 3},
{4, 5, 6},
{7, 8, 9, 10}
};
System.out.println("\n三角形数组:");
for (int[] row : triangle) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
}
}二维数组应用
java
public class TwoDArrayApplications {
public static void main(String[] args) {
// 矩阵加法
int[][] a = {
{1, 2, 3},
{4, 5, 6}
};
int[][] b = {
{7, 8, 9},
{10, 11, 12}
};
int[][] sum = new int[2][3];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
sum[i][j] = a[i][j] + b[i][j];
}
}
System.out.println("矩阵加法结果:");
printMatrix(sum);
// 矩阵转置
int[][] original = {
{1, 2, 3},
{4, 5, 6}
};
int rows = original.length;
int cols = original[0].length;
int[][] transposed = new int[cols][rows];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
transposed[j][i] = original[i][j];
}
}
System.out.println("\n矩阵转置:");
System.out.println("原矩阵:");
printMatrix(original);
System.out.println("转置后:");
printMatrix(transposed);
// 杨辉三角
System.out.println("\n杨辉三角(10行):");
int[][] yanghui = new int[10][];
for (int i = 0; i < yanghui.length; i++) {
yanghui[i] = new int[i + 1];
yanghui[i][0] = 1; // 每行第一个元素
yanghui[i][i] = 1; // 每行最后一个元素
// 计算中间元素
for (int j = 1; j < i; j++) {
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
}
}
// 打印杨辉三角
for (int[] row : yanghui) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
}
// 打印矩阵
public static void printMatrix(int[][] matrix) {
for (int[] row : matrix) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
}
}Arrays 工具类
java.util.Arrays 类提供了很多操作数组的方法。
java
import java.util.Arrays;
public class ArraysClass {
public static void main(String[] args) {
int[] arr = {3, 1, 4, 1, 5, 9, 2, 6};
// 1. toString():数组转字符串
System.out.println("toString: " + Arrays.toString(arr));
// 2. sort():排序
int[] arr2 = arr.clone();
Arrays.sort(arr2);
System.out.println("sort: " + Arrays.toString(arr2));
// 3. binarySearch():二分查找(数组必须有序)
int index = Arrays.binarySearch(arr2, 5);
System.out.println("5 的索引: " + index);
// 4. fill():填充数组
int[] filled = new int[5];
Arrays.fill(filled, 100);
System.out.println("fill: " + Arrays.toString(filled));
// 部分填充
int[] partial = new int[10];
Arrays.fill(partial, 2, 7, 50); // 索引2到6填充50
System.out.println("部分填充: " + Arrays.toString(partial));
// 5. copyOf():复制数组
int[] copied = Arrays.copyOf(arr, 5); // 复制前5个元素
System.out.println("copyOf(5): " + Arrays.toString(copied));
int[] expanded = Arrays.copyOf(arr, 15); // 扩展长度
System.out.println("copyOf(15): " + Arrays.toString(expanded));
// 6. copyOfRange():范围复制
int[] range = Arrays.copyOfRange(arr, 2, 6); // 复制索引2到5
System.out.println("copyOfRange(2,6): " + Arrays.toString(range));
// 7. equals():比较数组内容
int[] a1 = {1, 2, 3};
int[] a2 = {1, 2, 3};
int[] a3 = {1, 2, 4};
System.out.println("a1 == a2: " + (a1 == a2)); // false
System.out.println("equals(a1, a2): " + Arrays.equals(a1, a2)); // true
System.out.println("equals(a1, a3): " + Arrays.equals(a1, a3)); // false
// 8. 二维数组操作
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = {{1, 2}, {3, 4}};
System.out.println("deepToString: " + Arrays.deepToString(matrix1));
System.out.println("deepEquals: " + Arrays.deepEquals(matrix1, matrix2));
}
}数组常见问题
数组越界
java
public class ArrayIndexOutOfBounds {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
// 正确访问
System.out.println("arr[0] = " + arr[0]);
System.out.println("arr[4] = " + arr[4]);
// 数组越界(运行时错误)
try {
System.out.println(arr[5]); // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界异常: " + e.getMessage());
}
try {
System.out.println(arr[-1]); // 负数索引
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("负数索引异常: " + e.getMessage());
}
// 安全访问方式
int index = 5;
if (index >= 0 && index < arr.length) {
System.out.println(arr[index]);
} else {
System.out.println("索引 " + index + " 超出范围");
}
}
}空指针异常
java
public class NullPointerArray {
public static void main(String[] args) {
int[] arr = null;
// 空指针异常
try {
System.out.println(arr.length); // NullPointerException
} catch (NullPointerException e) {
System.out.println("空指针异常: 数组为 null");
}
// 安全访问方式
if (arr != null) {
System.out.println(arr.length);
} else {
System.out.println("数组为 null");
}
}
}数组复制
java
public class ArrayCopy {
public static void main(String[] args) {
int[] original = {1, 2, 3, 4, 5};
// 方式一:循环复制
int[] copy1 = new int[original.length];
for (int i = 0; i < original.length; i++) {
copy1[i] = original[i];
}
// 方式二:clone()
int[] copy2 = original.clone();
// 方式三:Arrays.copyOf()
int[] copy3 = Arrays.copyOf(original, original.length);
// 方式四:System.arraycopy()
int[] copy4 = new int[original.length];
System.arraycopy(original, 0, copy4, 0, original.length);
// 验证:修改原数组不影响副本
original[0] = 100;
System.out.println("原数组: " + Arrays.toString(original));
System.out.println("副本1: " + Arrays.toString(copy1));
// 浅拷贝问题(引用类型数组)
Person[] persons = {new Person("张三"), new Person("李四")};
Person[] personsCopy = persons.clone();
// 修改对象属性会影响副本
persons[0].name = "王五";
System.out.println("\n原数组: " + persons[0].name); // 王五
System.out.println("副本: " + personsCopy[0].name); // 王五(也变了)
}
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
}数组与算法
二分查找
java
import java.util.Arrays;
public class BinarySearch {
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int target = 7;
int index = binarySearch(arr, target);
System.out.println("查找 " + target + ",索引: " + index);
target = 8;
index = binarySearch(arr, target);
System.out.println("查找 " + target + ",索引: " + index); // -1(未找到)
}
/**
* 二分查找(非递归)
* @param arr 有序数组
* @param target 目标值
* @return 索引,未找到返回 -1
*/
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 防止溢出
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1; // 未找到
}
}数组反转
java
import java.util.Arrays;
public class ArrayReverse {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6};
System.out.println("原数组: " + Arrays.toString(arr));
// 方式一:双指针
int[] arr1 = arr.clone();
int left = 0, right = arr1.length - 1;
while (left < right) {
int temp = arr1[left];
arr1[left] = arr1[right];
arr1[right] = temp;
left++;
right--;
}
System.out.println("反转后: " + Arrays.toString(arr1));
// 方式二:新建数组
int[] arr2 = arr.clone();
int[] reversed = new int[arr2.length];
for (int i = 0; i < arr2.length; i++) {
reversed[i] = arr2[arr2.length - 1 - i];
}
System.out.println("新数组反转: " + Arrays.toString(reversed));
}
}小结
本章我们学习了:
- 一维数组:声明、初始化、遍历、操作
- 二维数组:规则数组和不规则数组
- Arrays 工具类:排序、查找、复制、填充等
- 数组常见问题:越界、空指针、浅拷贝
- 数组算法:排序、查找、反转
下一章,我们将学习 面向对象基础,了解 Java 面向对象编程的核心概念。
