Java 数组详解
1. 数组基础概念
1.1 什么是数组
数组是Java中用来存储固定大小的同类型元素的线性数据结构。数组在内存中是连续分配的。
1.2 数组特点
- 固定长度,一旦创建不能改变大小
- 所有元素类型相同
- 通过索引访问,索引从0开始
- 可以是基本数据类型或引用类型
2. 数组的声明和初始化
2.1 声明数组
// 方式1:数据类型[] 数组名
int[] numbers;
String[] names;
// 方式2:数据类型 数组名[] (不推荐)
int numbers[];
2.2 初始化数组
// 1. 动态初始化 - 先声明,后分配空间
int[] arr1;
arr1 = new int[5]; // 创建长度为5的int数组
// 2. 静态初始化 - 声明时直接赋值
int[] arr2 = {1, 2, 3, 4, 5};
int[] arr3 = new int[]{1, 2, 3, 4, 5};
// 3. 默认值初始化
int[] arr4 = new int[3]; // 所有元素默认为0
boolean[] flags = new boolean[3]; // 所有元素默认为false
String[] strs = new String[3]; // 所有元素默认为null
3. 数组的常用属性
3.1 length 属性
int[] numbers = {1, 2, 3, 4, 5};
System.out.println("数组长度: " + numbers.length); // 输出: 5
// 遍历数组的常用方式
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
4. 数组的常用操作和方法
4.1 基本操作
// 创建和访问
int[] scores = {85, 92, 78, 96, 88};
// 访问元素
System.out.println("第一个元素: " + scores[0]); // 85
System.out.println("最后一个元素: " + scores[scores.length - 1]); // 88
// 修改元素
scores[2] = 90; // 将第三个元素从78改为90
// 遍历数组 - 传统for循环
for (int i = 0; i < scores.length; i++) {
System.out.println("索引 " + i + ": " + scores[i]);
}
// 遍历数组 - 增强for循环
for (int score : scores) {
System.out.println("分数: " + score);
}
4.2 使用Arrays工具类
import java.util.Arrays;
public class ArrayMethodsExample {
public static void main(String[] args) {
int[] arr1 = {5, 2, 8, 1, 9};
int[] arr2 = {1, 2, 3, 4, 5};
// 1. Arrays.toString() - 数组转字符串
System.out.println("数组内容: " + Arrays.toString(arr1));
// 2. Arrays.sort() - 数组排序
Arrays.sort(arr1);
System.out.println("排序后: " + Arrays.toString(arr1));
// 3. Arrays.binarySearch() - 二分查找(必须先排序)
int index = Arrays.binarySearch(arr1, 8);
System.out.println("元素8的索引: " + index);
// 4. Arrays.equals() - 比较数组是否相等
System.out.println("数组相等: " + Arrays.equals(arr1, arr2));
// 5. Arrays.copyOf() - 复制数组
int[] arr3 = Arrays.copyOf(arr1, arr1.length);
System.out.println("复制数组: " + Arrays.toString(arr3));
// 6. Arrays.copyOfRange() - 复制指定范围
int[] arr4 = Arrays.copyOfRange(arr1, 1, 4);
System.out.println("范围复制: " + Arrays.toString(arr4));
// 7. Arrays.fill() - 填充数组
int[] arr5 = new int[5];
Arrays.fill(arr5, 10);
System.out.println("填充后: " + Arrays.toString(arr5));
}
}
4.3 多维数组
// 二维数组的声明和初始化
int[][] matrix1 = new int[3][3]; // 3x3矩阵
int[][] matrix2 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 访问二维数组元素
System.out.println("第二行第三列: " + matrix2[1][2]); // 6
// 遍历二维数组
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[][] irregularArray = new int[3][];
irregularArray[0] = new int[2];
irregularArray[1] = new int[3];
irregularArray[2] = new int[1];
5. 数组的实用工具方法
5.1 自定义数组工具类
public class ArrayUtils {
// 查找最大值
public static int findMax(int[] arr) {
if (arr == null || arr.length == 0) {
throw new IllegalArgumentException("数组不能为空");
}
int max = arr[0];
for (int num : arr) {
if (num > max) {
max = num;
}
}
return max;
}
// 查找最小值
public static int findMin(int[] arr) {
if (arr == null || arr.length == 0) {
throw new IllegalArgumentException("数组不能为空");
}
int min = arr[0];
for (int num : arr) {
if (num < min) {
min = num;
}
}
return min;
}
// 计算平均值
public static double calculateAverage(int[] arr) {
if (arr == null || arr.length == 0) {
throw new IllegalArgumentException("数组不能为空");
}
int sum = 0;
for (int num : arr) {
sum += num;
}
return (double) sum / arr.length;
}
// 反转数组
public static void reverse(int[] arr) {
if (arr == null) return;
int left = 0;
int right = arr.length - 1;
while (left < right) {
// 交换元素
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
// 查找元素索引
public static int indexOf(int[] arr, int target) {
if (arr == null) return -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i;
}
}
return -1;
}
}
5.2 使用示例
public class ArrayDemo {
public static void main(String[] args) {
int[] numbers = {23, 45, 12, 67, 89, 34};
// 使用自定义工具类
System.out.println("最大值: " + ArrayUtils.findMax(numbers));
System.out.println("最小值: " + ArrayUtils.findMin(numbers));
System.out.println("平均值: " + ArrayUtils.calculateAverage(numbers));
System.out.println("反转前: " + Arrays.toString(numbers));
ArrayUtils.reverse(numbers);
System.out.println("反转后: " + Arrays.toString(numbers));
// 查找元素
int index = ArrayUtils.indexOf(numbers, 67);
System.out.println("67的索引: " + index);
// 数组拷贝的注意事项
int[] original = {1, 2, 3};
int[] shallowCopy = original; // 浅拷贝
int[] deepCopy = Arrays.copyOf(original, original.length); // 深拷贝
original[0] = 100;
System.out.println("浅拷贝受影响: " + shallowCopy[0]); // 100
System.out.println("深拷贝不受影响: " + deepCopy[0]); // 1
}
}
6. 数组的注意事项和最佳实践
6.1 常见错误
// 1. 数组越界
int[] arr = {1, 2, 3};
// System.out.println(arr[3]); // ArrayIndexOutOfBoundsException
// 2. 空指针异常
int[] nullArray = null;
// System.out.println(nullArray.length); // NullPointerException
// 3. 类型不匹配
// String[] strs = {1, 2, 3}; // 编译错误
6.2 最佳实践
public class ArrayBestPractices {
public static void main(String[] args) {
// 1. 总是检查数组是否为null
int[] arr = null;
if (arr != null && arr.length > 0) {
System.out.println("数组安全访问");
}
// 2. 使用增强for循环避免索引错误
int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
System.out.println(num); // 不会出现索引越界
}
// 3. 使用System.arraycopy进行高效数组拷贝
int[] source = {1, 2, 3, 4, 5};
int[] destination = new int[5];
System.arraycopy(source, 0, destination, 0, source.length);
// 4. 对于对象数组,注意深浅拷贝的区别
Person[] persons = {new Person("Alice"), new Person("Bob")};
Person[] shallowCopy = persons; // 浅拷贝
Person[] deepCopy = Arrays.copyOf(persons, persons.length); // 深拷贝(但对象本身还是共享的)
}
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
}
7. 数组与集合的转换
import java.util.*;
public class ArrayCollectionConversion {
public static void main(String[] args) {
// 数组转List
String[] array = {"Java", "Python", "C++"};
List<String> list = Arrays.asList(array);
System.out.println("List: " + list);
// List转数组
List<Integer> numberList = new ArrayList<>();
numberList.add(1);
numberList.add(2);
numberList.add(3);
Integer[] numberArray = numberList.toArray(new Integer[0]);
System.out.println("Array: " + Arrays.toString(numberArray));
// 使用Stream API
int[] primitiveArray = {1, 2, 3, 4, 5};
List<Integer> streamList = Arrays.stream(primitiveArray)
.boxed()
.collect(Collectors.toList());
System.out.println("Stream转换: " + streamList);
}
}
总结
Java数组是基础且重要的数据结构,掌握其特性和常用方法对于Java编程至关重要。记住数组的固定大小特性,合理使用Arrays工具类,注意数组拷贝的深浅问题,这些都是编写高质量Java代码的关键。