上文链接:https://blog.csdn.net/weixin_73492487/article/details/146164026
1.方法重载和重写的区别?
答:重载是同类的同名不同参方法,重写是子类覆盖父类方法
2.如何解决递归栈溢出?
答:① 改用循环迭代 ② 增大栈空间(-Xss参数)③ 尾递归优化(伪实现)
3.以下代码输出什么?
public static void change(String s) {
s = "new";
}
public static void main(String[] args) {
String str = "old";
change(str);
System.out.println(str); // 输出"old"
}
4.可变参数方法能接收null吗?
答:可以,但需做空判断(nums == null)
定义: Java 语言中提供的数组是用来存储固定大小的同类型元素。你可以声明一个数组变量,如 nums[100] 来代替直接声明 100 个独立变量 num0,num1,…,num99
java数组本质上是一种对象(后文会具体解释)
创建:
// 一维数组
int[] arr1; // 声明(推荐)
int arr2[]; // 声明(C风格,不推荐)
arr1 = new int[5]; // 动态初始化(先有声明,再有初始化,默认值0)
int[] arr2=new int[5];
// 二维数组
int[][] matrix = new int[3][4]; // 规则二维数组
int[][] jagged = new int[2][]; // 锯齿数组(每行长度不同)
类型 | 语法示例 | 特点 |
---|---|---|
静态初始化 | int[] arr = {1,2,3}; |
直接指定元素值 |
动态初始化 | String[] names = new String[3]; |
指定长度,赋默认值 |
默认初始化 | 数组元素自动初始化 | 根据类型:int→0,对象→null |
内存分析:
数组是动态分配在堆内存中的对象。这与 Java 中其他类型的对象类似(例如实例化的类对象)。与局部变量或基本数据类型(如 int)不同,数组对象是通过 new 关键字创建的,并且分配的内存由 JVM 管理。
arr1
)是引用,存储堆中数组对象的地址int[] arr = new int[5];
System.out.println(arr.length); // 获取数组长度(非方法)
每个数组对象都有一个内建的属性 .length,这个属性表示数组的长度(即数组中元素的数量)。它具有作为对象的特性。
// 基础for循环
for(int i=0; i<arr.length; i++){...}
// 增强for循环(只读)
for(int num : arr) {...} //快捷写法:arrays.for
// 二维数组遍历
for(int[] row : matrix) {
for(int num : row) {...}
}
下标越界:ArrayIndexOutOfBoundsException
int[] arr = new int[3];
arr[3] = 5; // 最大合法索引为2
空指针异常:
int[][] arr = new int[2][];
System.out.println(arr[0][0]); // NullPointerException
解释:arr 是一个长度为 2 的数组,每个元素应该是一个 int[] 数组(即二维数组的行)。但每个int[]子数组尚未初始化,所以它们的默认值为 null。
长度不可变:数组创建后长度固定
栈内存 堆内存
arr → [0][0][0][0][0](以int[5]为实例)
matrix → [ [0,0,0,0] ] // matrix[0]指向第一个子数组
[ [0,0,0,0] ]
[ [0,0,0,0] ] //matrix[3][4]
public static void modify(int[] arr) {
arr[0] = 100; // 修改会影响原始数组(引用传递,实际上也是值传递,但这个值指向对象的内存地址)
}
数组声明方式是否正确?
int[] arr1 = new int[3]{1,2,3}; // 错误(动态初始化不能指定元素)
int[][] arr2 = new int[][3]; // 错误(必须指定行数)
以下代码输出什么?
int[] arr = new int[5];
System.out.println(arr[0]); // 0(int默认值)
String[] strs = new String[3];
System.out.println(strs[1]); // null(对象默认值)
如何实现数组深拷贝?(浅拷贝与深拷贝的区别,基本数据类型不分深拷贝与浅拷贝)
int[] src = {1,2,3};
int[] dest = Arrays.copyOf(src, src.length); //使用 Arrays.copyOf() 进行深拷贝
// 或
System.arraycopy(src, 0, dest, 0, src.length); //使用 System.arraycopy() 方法
数组与ArrayList的区别?(以后会学到ArrayList类,可以提前了解)
// 数组动态扩容
int[] arr = {1,2,3};
arr = Arrays.copyOf(arr, arr.length * 2); // 容量翻倍
// 数组判空技巧
if(array == null || array.length == 0) {
// 处理空数组情况
}
// 不规则二维数组
int[][] matrix = new int[3][];
matrix[0] = new int[2];
matrix[1] = new int[4];
matrix[2] = new int[3];
栈内存 堆内存
arrRef → [ [@1001, @1002], // 二维数组引用
[@1003, null ] ]
@1001: [1,2,3] // 第一行数组
@1002: [4,5] // 第二行数组
@1003: [6] // 第三行数组
方法 | 功能描述 | 示例 |
---|---|---|
Arrays.toString(arr) |
数组转字符串 | "[1, 2, 3]" |
Arrays.sort(arr) |
数组排序(优化快排) | 原数组被修改 |
Arrays.binarySearch(arr, key) |
二分查找(需先排序) | 返回索引或插入点负值 |
Arrays.copyOfRange() |
复制指定范围数组 | copyOfRange(src, 1, 4) |
Arrays.fill(arr, val) |
填充数组 | fill(arr, -1) |
Arrays.equals(arr1, arr2) |
深度比较数组内容 | 多维数组也可比较 |
Arrays.parallelSort(largeArray); // 并行排序(大数据量更快)
该方法用于并行排序数组中的元素。它通过多线程将排序任务划分为多个小任务,在多个处理器核心上并行执行,从而加快排序过程,尤其是在处理大数组时。
对于大数组或复杂排序操作,使用并行排序能够有效提升性能,因为它能够利用多核处理器的优势。
稀疏数组(Sparse Array)是一种用于存储大部分元素为零(或空)的数组数据结构。通常,稀疏数组用于节省内存空间
,尤其是在处理二维或更高维度的大数组时。如果一个数组中的大部分元素都是相同的、重复的(例如零或 null),使用稀疏数组可以仅存储非零的元素和它们的位置信息,从而大大节省空间。
存储大量重复默认值(通常为0)的二维数组时,压缩存储:
原始数组(5x5):
0 0 0 0 0
0 2 0 0 0
0 0 3 0 0
0 0 0 0 0
0 0 0 0 0
稀疏数组:
(行数 列数 非零元素个数)
5 5 2 // 行数 列数 非零元素个数
(行 列 值)
1 1 2 // 行 列 值
2 2 3
代码:
public class SparseArray {
// 定义一个稀疏数组,存储稀疏数组的三元组
private int[][] sparseArray;
// 构造函数,接受原始数组的行数、列数和非零元素的个数
public SparseArray(int rows, int cols, int nonZeroCount) {
sparseArray = new int[nonZeroCount + 1][3]; // 多一行用于存储数组的元信息
sparseArray[0][0] = rows; // 存储原数组的行数
sparseArray[0][1] = cols; // 存储原数组的列数
sparseArray[0][2] = nonZeroCount; // 存储非零元素的个数
}
// 设置稀疏数组中的值
public void set(int index, int row, int col, int value) { //index对应第几个非零元素
sparseArray[index + 1][0] = row;
sparseArray[index + 1][1] = col;
sparseArray[index + 1][2] = value;
}
// 获取稀疏数组中的值
public int[] get(int index) {
return sparseArray[index + 1];
}
// 打印稀疏数组
public void print() {
for (int i = 0; i < sparseArray.length; i++) {
System.out.println(sparseArray[i][0] + "\t" + sparseArray[i][1] + "\t" + sparseArray[i][2]);
}
}
// 主函数:将一个普通的二维数组转化为稀疏数组
public static SparseArray toSparseArray(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
int nonZeroCount = 0;
// 计算非零元素个数
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] != 0) {
nonZeroCount++;
}
}
}
SparseArray sparseArray = new SparseArray(rows, cols, nonZeroCount);
// 将非零元素存入稀疏数组
int index = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (matrix[i][j] != 0) {
sparseArray.set(index, i, j, matrix[i][j]);
index++;
}
}
}
return sparseArray;
}
public static void main(String[] args) {
// 原始二维数组
int[][] matrix = {
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 3, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 4, 0}
};
SparseArray sparseArray = SparseArray.toSparseArray(matrix);
sparseArray.print();
}
}
输出结果:
5 5 2
2 1 3
4 3 4
1.优点:
节省内存
:只存储非零元素,适合大多数元素为零的情况。提高效率
:减少了存储空间的浪费,尤其在存储稀疏数据时,可以显著降低内存占用。图像处理
:图像中大多数像素值为零(黑色或透明),使用稀疏数组能够有效地存储图像数据。棋盘、地图等
:例如,在棋盘游戏、路径寻找等场景中,大多数位置为空,稀疏数组可以节省空间。图的表示
:在图的邻接矩阵表示中,很多元素为零(即无边),可以使用稀疏数组来存储图