Java 数组

来源:Chatgpt-4o

在 Java 中,数组是一种用于存储固定数量、同类型元素的数据结构。它非常高效,适合用来存储和访问大量数据。

基础操作

1️⃣ 数组声明和初始化

声明数组:

1
2
int[] numbers;    // 推荐写法
int numbers[]; // 也可以这样,但不太推荐

分配内存:

1
numbers = new int[5]; // 创建一个长度为5的整数数组,默认值为0

声明并初始化:

1
int[] numbers = {1, 2, 3, 4, 5}; // 静态初始化,直接赋值

动态初始化:

1
2
3
4
int[] numbers = new int[3];     // 创建一个长度为3的数组
numbers[0] = 10; // 给数组元素赋值
numbers[1] = 20;
numbers[2] = 30;

2️⃣ 数组基本操作

访问元素:

1
System.out.println(numbers[0]); // 输出第一个元素,10

修改元素:

1
numbers[1] = 99; // 把第二个元素改为99

获取数组长度:

1
System.out.println(numbers.length); // 输出数组长度

3️⃣ 遍历数组

for 循环:

1
2
3
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}

增强型 for 循环(foreach):

1
2
3
for (int num : numbers) {
System.out.println(num);
}

4️⃣ 多维数组

声明和初始化二维数组:

1
2
3
4
5
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};

访问二维数组元素:

1
System.out.println(matrix[1][2]); // 输出6

遍历二维数组:

1
2
3
4
5
6
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}

5️⃣ 常见问题

数组越界异常:

1
2
int[] arr = new int[3];
System.out.println(arr[3]); // java.lang.ArrayIndexOutOfBoundsException

数组默认值:

  • intlongshortbyte -> 0
  • floatdouble -> 0.0
  • boolean -> false
  • char -> \u0000 (空字符)
  • 引用类型 -> null

Java Arrays

java.util.Arrays 是 Java 中非常强大的一个工具类,提供了对数组的操作方法,比如排序、搜索、比较、填充、转换等。


1️⃣ 导包

首先要导入 Arrays 类所在的包:

1
import java.util.Arrays;

2️⃣ 常用方法

(1)数组排序 — Arrays.sort()

升序排列数组:

1
2
3
int[] numbers = {5, 2, 8, 1, 3};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers)); // 输出:[1, 2, 3, 5, 8]

对部分数组排序:

1
2
3
int[] numbers = {5, 2, 8, 1, 3};
Arrays.sort(numbers, 1, 4); // 对索引1到3进行排序(不包括索引4)
System.out.println(Arrays.toString(numbers)); // 输出:[5, 1, 2, 8, 3]

(2)数组转换为字符串 — Arrays.toString()

把一维数组转换为字符串:

1
2
String[] names = {"Alice", "Bob", "Charlie"};
System.out.println(Arrays.toString(names)); // 输出:[Alice, Bob, Charlie]

把二维数组转换为字符串:

1
2
int[][] matrix = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepToString(matrix)); // 输出:[[1, 2], [3, 4]]

(3)数组填充 — Arrays.fill()

将数组所有元素填充为同一个值:

1
2
3
int[] arr = new int[5];
Arrays.fill(arr, 7);
System.out.println(Arrays.toString(arr)); // 输出:[7, 7, 7, 7, 7]

对部分数组填充:

1
2
3
int[] arr = new int[5];
Arrays.fill(arr, 1, 4, 9); // 填充索引1到3(不包括索引4)
System.out.println(Arrays.toString(arr)); // 输出:[0, 9, 9, 9, 0]

(4)数组比较 — Arrays.equals()Arrays.deepEquals()

比较一维数组:

1
2
3
int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};
System.out.println(Arrays.equals(arr1, arr2)); // 输出:true

比较多维数组:

1
2
3
int[][] arr1 = {{1, 2}, {3, 4}};
int[][] arr2 = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepEquals(arr1, arr2)); // 输出:true

(5)数组复制 — Arrays.copyOf()Arrays.copyOfRange()

复制整个数组:

1
2
3
int[] numbers = {1, 2, 3, 4, 5};
int[] copy = Arrays.copyOf(numbers, numbers.length);
System.out.println(Arrays.toString(copy)); // 输出:[1, 2, 3, 4, 5]

复制部分数组:

1
2
3
int[] numbers = {1, 2, 3, 4, 5};
int[] part = Arrays.copyOfRange(numbers, 1, 4); // 从索引1到索引3(不包括4)
System.out.println(Arrays.toString(part)); // 输出:[2, 3, 4]

(6)数组搜索 — Arrays.binarySearch()

在有序数组中查找元素(必须是已排序数组!)(是二分查找):

1
2
3
int[] numbers = {1, 3, 5, 7, 9};
int index = Arrays.binarySearch(numbers, 5);
System.out.println(index); // 输出:2 (元素5的索引位置)

如果找不到会返回负数:

1
2
int index = Arrays.binarySearch(numbers, 6);
System.out.println(index); // 输出:-4 (表示6应该插入在索引3的位置)

3️⃣ 综合练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.Arrays;

public class ArraysExample {
public static void main(String[] args) {
int[] numbers = {42, 12, 56, 7, 23};

// 排序
Arrays.sort(numbers);
System.out.println("排序后: " + Arrays.toString(numbers));

// 填充
Arrays.fill(numbers, 2, 4, 99);
System.out.println("填充后: " + Arrays.toString(numbers));

// 复制
int[] copy = Arrays.copyOf(numbers, numbers.length);
System.out.println("复制的数组: " + Arrays.toString(copy));

// 比较
System.out.println("数组是否相等: " + Arrays.equals(numbers, copy));

// 搜索
int index = Arrays.binarySearch(numbers, 99);
System.out.println("99 的索引: " + index);
}
}

输出结果:

1
2
3
4
5
排序后: [7, 12, 23, 42, 56]
填充后: [7, 12, 99, 99, 56]
复制的数组: [7, 12, 99, 99, 56]
数组是否相等: true
99 的索引: 2

4️⃣ 小技巧

  • 数组快速初始化:

    1
    2
    int[] arr = new int[]{1, 2, 3}; // 标准写法
    int[] arr = {1, 2, 3}; // 简写
  • 排序降序:(使用 Comparator

    1
    2
    3
    Integer[] numbers = {5, 2, 8, 1, 3};
    Arrays.sort(numbers, (a, b) -> b - a);
    System.out.println(Arrays.toString(numbers)); // 输出:[8, 5, 3, 2, 1]
  • 数组转换为 List

    1
    2
    3
    String[] names = {"Alice", "Bob", "Charlie"};
    List<String> nameList = Arrays.asList(names);
    System.out.println(nameList); // 输出:[Alice, Bob, Charlie]

自定义比较器降序排序原理

Arrays.sort(T[] a, Comparator<? super T> c) 方法,搭配了一个自定义比较器(Comparator)

首先,这个方法需要一个比较器(Comparator),这个比较器决定数组元素之间的排序规则。

1
Arrays.sort(numbers, (a, b) -> b - a);

这里 (a, b) -> b - a 是一个 Lambda 表达式,本质上是一个实现了 Comparator<T> 接口的匿名方法。等效于:

1
2
3
4
5
6
7
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return b - a; // 降序排序规则
}
};
Arrays.sort(numbers, comparator);

💡 那为什么 b - a 能实现降序呢?
Comparator 接口的 compare() 方法定义:

1
int compare(T o1, T o2);

这个方法返回一个 int,比较两个元素时的返回值决定了排序顺序:

  • < 0:表示 o1 应该排在 o2 前面。
  • > 0:表示 o1 应该排在 o2 后面。
  • = 0:表示两个元素相等,顺序不变。

我们来看看 b - a 是怎么影响排序的:

假设数组是:

1
Integer[] numbers = {5, 2, 8, 1, 3};

比较两个数 a = 5b = 2

1
b - a = 2 - 5 = -3  // 返回负数,表示 5 应该排在 2 的前面(降序)

比较两个数 a = 8b = 5

1
b - a = 5 - 8 = -3  // 8 应该排在 5 的前面(降序)

所以这个写法实现了降序排序。


✨ 总结一下:

  • b - a 是降序排序,因为当 ba 小时,返回负数,a 会被排在前面。
  • 如果想要升序排序,就用 a - b(默认行为)。
  • Arrays.sort() 搭配自定义比较器非常灵活,适用于复杂对象排序。

📝 拓展:用 Collections.reverseOrder() 也可以降序:

1
2
3
Integer[] numbers = {5, 2, 8, 1, 3};
Arrays.sort(numbers, Collections.reverseOrder());
System.out.println(Arrays.toString(numbers)); // 输出:[8, 5, 3, 2, 1]