Java Arrays案例如何操作数组

wen java案例 30

Java Arrays案例:如何高效操作数组?从基础到实战全解析

目录导读

  1. 数组基础:定义与初始化
  2. 数组遍历与元素访问
  3. 数组排序与搜索实战
  4. 数组复制与扩容技巧
  5. 多维数组操作案例
  6. Arrays工具类核心方法
  7. 高频问题与最佳实践
  8. 常见问答

数组基础:定义与初始化

数组是Java中最基础的数据结构之一,它是一组相同类型数据的容器,具有固定长度和连续内存空间的特点。

Java Arrays案例如何操作数组

声明与初始化方式:

// 方式一:静态初始化
int[] scores = {85, 92, 78, 90, 88};
// 方式二:动态初始化
String[] names = new String[5];
names[0] = "Alice";
names[1] = "Bob";
// 方式三:数组字面量(仅限声明时)
int[] numbers = new int[]{1, 2, 3, 4, 5};

注意:数组长度一旦确定不可改变,但可以重新赋值引用指向新数组对象,对于引用类型数组,每个元素初始值为null;对于基本类型数组,如int初始值为0,booleanfalse

案例:学生成绩系统初始化

class ScoreManager {
    public static void main(String[] args) {
        // 创建包含5名学生的成绩数组
        int[] studentScores = {88, 76, 95, 82, 67};
        System.out.println("成绩总数: " + studentScores.length);
        // 输出: 成绩总数: 5
    }
}

数组遍历与元素访问

数组的索引从0开始,通过数组名[索引]方式访问元素,常见的遍历方式有for循环、增强for循环以及Java 8+的Stream API。

三种遍历方式演示:

public class ArrayTraversal {
    public static void main(String[] args) {
        int[] arr = {10, 20, 30, 40, 50};
        // 1. 传统for循环
        for (int i = 0; i < arr.length; i++) {
            System.out.println("索引" + i + ": " + arr[i]);
        }
        // 2. 增强for循环(for-each)
        for (int num : arr) {
            System.out.println("值为: " + num);
        }
        // 3. Java 8 Stream方式
        Arrays.stream(arr).forEach(System.out::println);
    }
}

边界安全提示:
始终使用arr.length作为循环条件,避免硬编码索引值,当访问arr[arr.length]时会抛出ArrayIndexOutOfBoundsException

操作案例:查找最大值

public static int findMax(int[] numbers) {
    if (numbers == null || numbers.length == 0) {
        throw new IllegalArgumentException("数组不能为空");
    }
    int max = numbers[0];
    for (int num : numbers) {
        if (num > max) {
            max = num;
        }
    }
    return max;
}

数组排序与搜索实战

Java提供了Arrays.sort()Arrays.binarySearch()等便捷方法,排序前必须保证数组已排序才能使用二分搜索。

完整排序+搜索案例:

import java.util.Arrays;
public class SortAndSearchDemo {
    public static void main(String[] args) {
        int[] data = {42, 17, 8, 99, 23, 56, 3};
        // 原始数组
        System.out.println("原始数组: " + Arrays.toString(data));
        // 排序(内部使用Dual-Pivot Quicksort)
        Arrays.sort(data);
        System.out.println("排序后: " + Arrays.toString(data));
        // 二分搜索(必须有序)
        int target = 23;
        int index = Arrays.binarySearch(data, target);
        if (index >= 0) {
            System.out.println("找到 " + target + " 在索引 " + index);
        } else {
            System.out.println(target + " 未找到,应插入位置: " + (-index - 1));
        }
    }
}

自定义排序(对象数组):

// 对学生对象按成绩排序
class Student implements Comparable<Student> {
    String name;
    int score;
    @Override
    public int compareTo(Student other) {
        return Integer.compare(this.score, other.score); // 升序
    }
}
Student[] students = {new Student("Tom", 88), new Student("Jerry", 95)};
Arrays.sort(students); // 自然排序
Arrays.sort(students, (a, b) -> b.score - a.score); // 降序(Lambda)

数组复制与扩容技巧

由于数组长度固定,需要扩容时通常创建新数组并复制元素,推荐使用System.arraycopy()Arrays.copyOf()

高效复制方法对比:

// 方法1:System.arraycopy(底层native实现,性能最高)
int[] source = {1, 2, 3, 4, 5};
int[] dest = new int[10];
System.arraycopy(source, 0, dest, 0, source.length);
// 方法2:Arrays.copyOf(内部调用arraycopy)
int[] newArr = Arrays.copyOf(source, 10); // 多余元素补0
// 方法3:手动循环(不推荐,效率低)
int[] manualCopy = new int[source.length];
for (int i = 0; i < source.length; i++) {
    manualCopy[i] = source[i];
}

实际扩容案例:动态添加元素

public class DynamicArray {
    private int[] data;
    private int size;
    public DynamicArray(int initialCapacity) {
        data = new int[initialCapacity];
        size = 0;
    }
    public void add(int value) {
        if (size >= data.length) {
            // 扩容到1.5倍
            data = Arrays.copyOf(data, data.length + (data.length >> 1));
        }
        data[size++] = value;
    }
}

多维数组操作案例

多维数组本质上是数组的数组,最常见的是一维数组构成的二维表格数据结构。

二维数组的创建与遍历:

// 创建3*4的矩阵
int[][] matrix = new int[3][4];
// 或直接初始化
int[][] matrix2 = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
// 遍历(行优先)
for (int i = 0; i < matrix2.length; i++) {
    for (int j = 0; j < matrix2[i].length; j++) {
        System.out.print(matrix2[i][j] + " ");
    }
    System.out.println();
}

不规则数组(锯齿数组):

// 每行列数可以不同
int[][] irregular = new int[3][];
irregular[0] = new int[]{1, 2};
irregular[1] = new int[]{3, 4, 5};
irregular[2] = new int[]{6};

矩阵转置案例:

public static int[][] transpose(int[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[0].length;
    int[][] result = new int[cols][rows];
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            result[j][i] = matrix[i][j];
        }
    }
    return result;
}

Arrays工具类核心方法

java.util.Arrays包含20+个静态方法,极大简化数组操作,以下是高频使用的方法:

方法 功能 示例
sort() 排序 Arrays.sort(arr)
binarySearch() 二分查找 int idx = Arrays.binarySearch(arr, key)
fill() 填充 Arrays.fill(arr, 0)
equals() 比较 boolean eq = Arrays.equals(arr1, arr2)
toString() 转为字符串 String str = Arrays.toString(arr)
copyOf() 复制 int[] copy = Arrays.copyOf(original, newLen)
asList() 转为List List<Integer> list = Arrays.asList(1,2,3)
parallelSort() 并行排序(大数据量) Arrays.parallelSort(hugeArray)

实战:合并两个有序数组

public static int[] mergeSortedArrays(int[] arr1, int[] arr2) {
    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);
    Arrays.sort(merged);
    return merged;
}

注意事项:
Arrays.asList()返回的是固定大小的列表,不可调用add/remove方法,若要修改,应使用new ArrayList<>(Arrays.asList(...))


高频问题与最佳实践

问题1:数组与ArrayList如何选择?

  • 固定长度、基本类型集合、性能敏感场景 → 使用数组
  • 需要动态增删、类型安全、方便操作 → 使用ArrayList(底层仍是数组)

问题2:如何高效遍历大数组?

  • 使用普通for循环(非增强for)时,将arr.length提取为局部变量
  • 对于多线程处理,可使用Arrays.parallelSetAll()或Fork/Join框架

最佳实践清单:

  1. 始终检查数组是否为null和长度,避免空指针和越界
  2. 批量操作使用System.arraycopy而非手动循环
  3. 对对象数组排序时,确保实现了Comparable或提供Comparator
  4. 使用Arrays.fill()快速重置数组
  5. 将数组作为方法参数时,注意引用传递可能导致原数组被修改

案例:安全的数组拷贝防御性编程

public class ArraySafeCopy {
    private int[] internalData;
    public int[] getData() {
        // 返回副本而非原始引用,防止外部修改
        return Arrays.copyOf(internalData, internalData.length);
    }
    public void setData(int[] newData) {
        // 防御性复制,避免引用传递
        this.internalData = Arrays.copyOf(newData, newData.length);
    }
}

常见问答

Q1:数组可以直接用比较内容吗?
A:不可以。arr1 == arr2比较的是引用地址,而非元素内容,应使用Arrays.equals(arr1, arr2)进行值比较,对于多维数组,需用Arrays.deepEquals()

Q2:如何将数组转换为List以便添加元素?
A:先用Arrays.asList()转为固定大小List,再传入ArrayList构造器:

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
list.add(4); // 可行

Q3:int[]Integer[]有何区别?
A:int[]是基本类型数组,内存紧凑、性能高;Integer[]是引用类型数组,每个元素是对象,可配合泛型使用,在集合框架中只能使用Integer[]

Q4:如何获取数组的指定子数组?
A:使用Arrays.copyOfRange(arr, from, to)

int[] subArr = Arrays.copyOfRange(original, 2, 5); // 包含索引2,3,4

Q5:为什么Arrays.asList(1,2,3)返回的List不能add
A:因为返回的是Arrays内部类ArrayList,它继承自AbstractList,但未重写add方法,调用时抛出UnsupportedOperationException,要支持增删需包装到java.util.ArrayList中。


通过以上8个维度的深度解析,相信你已经掌握了Java数组从创建、遍历、排序到复制、多维操作的全部核心技能,数组虽然基础,但却是所有复杂数据结构(如堆、队列、哈希表)的基石,在实际项目中,灵活运用Arrays工具类并注意防御性编程,能让你的代码既高效又健壮。

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