Java案例如何操作数组?

wen java案例 10

从零掌握Java数组操作:10个典型案例与实战解惑

目录导读

  1. 数组基础回顾:声明、初始化与内存图解
  2. 数组元素遍历与查找
  3. 数组排序(冒泡与快速排序实战)
  4. 数组插入与删除(动态扩容技巧)
  5. 数组拷贝与合并(深拷贝与浅拷贝区别)
  6. 数组去重与统计(高频面试题)
  7. 二维数组操作(矩阵转置与求和)
  8. 数组与集合互转(List与Array的桥梁)
  9. 数组流式处理(Java 8 Stream API)
  10. 数组工具类Arrays详解
  11. 数组异常处理(NullPointer与IndexOutOfBounds)
  12. 问答环节:5个常见误区与解决方案

数组基础回顾

Java中的数组是存储固定大小同类型元素的容器,理解其本质对后续操作至关重要。

Java案例如何操作数组?

声明与初始化:

// 声明
int[] arr1;
// 静态初始化(直接赋值)
int[] arr2 = {1, 2, 3, 4};
// 动态初始化(指定长度)
String[] names = new String[5]; // 默认值null

内存图解:
数组在堆内存中是一块连续的空间,栈中的引用变量指向该空间的首地址。
典型错误:arr1 = {5, 6, 7}; 这种写法非法,必须用new或直接初始化。


案例一:数组元素遍历与查找

需求: 给定整数数组,查找目标值是否存在并返回下标。

代码实现:

public static int linearSearch(int[] arr, int target) {
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] == target) {
            return i;
        }
    }
    return -1; // 未找到
}

优化技巧:

  • 若数组有序,可用二分查找(时间复杂度O(log n))。
  • 使用增强for循环遍历但不适合返回下标。

案例二:数组排序

冒泡排序(稳定):

for (int i = 0; i < arr.length - 1; i++) {
    boolean swapped = false;
    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;
            swapped = true;
        }
    }
    if (!swapped) break; // 优化:没有交换则提前退出
}

快速排序(递归):
使用Arrays.sort(arr)即可,底层采用双轴快排,平均O(n log n)。


案例三:数组插入与删除

数组长度固定,插入/删除需要创建新数组。

插入操作:

public static int[] insertElement(int[] arr, int index, int value) {
    int[] newArr = new int[arr.length + 1];
    System.arraycopy(arr, 0, newArr, 0, index);
    newArr[index] = value;
    System.arraycopy(arr, index, newArr, index + 1, arr.length - index);
    return newArr;
}

删除操作:
类似思路,跳过目标索引复制即可。
注意:频繁的插入删除建议用ArrayList


案例四:数组拷贝与合并

浅拷贝 vs 深拷贝:

  • System.arraycopy()Arrays.copyOf() 属于浅拷贝(对象数组拷贝引用)。
  • 深拷贝需手动复制每个对象或使用序列化。

合并两个数组:

int[] merged = new int[arr1.length + arr2.length];
System.arraycopy(arr1, 0, merged, 0, arr1.length);
System.arraycopy(arr2, 0, merged, arr1.length, arr2.length);

案例五:数组去重与统计

痛点: 原始数组无序时如何高效去重?

方案:利用HashSet(推荐):

List<Integer> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();
for (int num : arr) {
    if (set.add(num)) {
        list.add(num); // 保留首次出现的顺序
    }
}

统计元素频率:
使用HashMap<Integer, Integer>


案例六:二维数组操作

矩阵转置:

int[][] matrix = {{1,2}, {3,4}, {5,6}}; // 3行2列
int rows = matrix.length;
int cols = matrix[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] = matrix[i][j];
    }
}

计算对角线之和: 注意方阵行列相等。


案例七:数组与集合互转

int[] 转 List(坑很多):

// 错误方式:Arrays.asList(int[]) 返回List<int[]> 并非List<Integer>
int[] arr = {1,2,3};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());

List变数组:

String[] array = list.toArray(new String[0]); // 推荐指定长度为0

案例八:数组流式处理

Java 8 Stream API 示例:

int[] numbers = {5, 3, 8, 1, 9};
int sum = Arrays.stream(numbers).sum();
double avg = Arrays.stream(numbers).average().orElse(0);
int[] filtered = Arrays.stream(numbers).filter(n -> n > 4).toArray();

并行处理:
Arrays.stream(numbers).parallel().forEach(...) 适合大数据量。


案例九:数组工具类Arrays详解

方法 用途 示例
sort() 排序 Arrays.sort(arr, 1, 4) 对部分排序
binarySearch() 二分查找前需排序 int idx = Arrays.binarySearch(arr, 3);
fill() 填充 Arrays.fill(arr, 0);
equals() 比较数组内容 Arrays.equals(a, b)
toString() 打印 Arrays.toString(arr)

注意: equals()deepEquals()区别(后者用于多维数组)。


案例十:数组异常处理

常见运行时异常:

  • ArrayIndexOutOfBoundsException:访问越界。
  • NullPointerException:对null数组调用length

防御性代码:

if (arr != null && arr.length > 0) {
    // 安全操作
}

问答环节:5个常见误区与解决方案

Q1: int[] a = new int[3]{1,2,3}; 为什么编译报错?
A: 动态初始化和静态初始化不能混用,正确写法:int[] a = {1,2,3};new int[]{1,2,3};

Q2: 数组的length是方法还是属性?
A: 是属性(arr.length),不是方法,String的length()是方法。

Q3: 如何高效地让数组所有元素乘以2?
A: 原始写法循环赋值;若使用Stream:Arrays.stream(arr).map(n -> n*2).toArray()

Q4: 为什么Arrays.asList()返回的List不能调用add()?
A: 返回的java.util.Arrays.ArrayList是内部类,固定大小,不支持增删操作。

Q5: 两个数组内容相同,但arr1.equals(arr2)返回false?
A: 数组没有重写equals(),默认比较引用,应使用Arrays.equals(arr1, arr2)

抱歉,评论功能暂时关闭!