Java 基于数组的专项 知识点
Java 数组专项知识点
一、数组基础与声明
1.1 数组基本概念
// 数组是相同类型数据的固定大小的顺序集合
public class ArrayBasics {
// 声明方式
int[] arr1; // 推荐
int arr2[]; // C风格,不推荐
// 初始化方式
int[] numbers = new int[5]; // 动态初始化
int[] scores = {90, 85, 88, 92, 78}; // 静态初始化
int[] values = new int[]{1, 2, 3}; // 完整语法
// 默认值
int[] intArr = new int[3]; // 默认: [0, 0, 0]
boolean[] boolArr = new boolean[2]; // 默认: [false, false]
String[] strArr = new String[2]; // 默认: [null, null]
}
1.2 数组属性与方法
public class ArrayProperties {
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
// 1. 数组长度(不可变)
System.out.println("长度: " + arr.length); // 5
// 2. 数组是对象
System.out.println(arr.getClass()); // class [I
System.out.println(arr instanceof Object); // true
// 3. 数组元素的访问
arr[0] = 100; // 修改第一个元素
int value = arr[2]; // 访问第三个元素
// 4. 数组越界异常
try {
arr[10] = 100; // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界!");
}
}
}
二、数组操作与遍历
2.1 遍历方法
public class ArrayTraversal {
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5};
// 1. 传统for循环(可控制索引)
for (int i = 0; i < nums.length; i++) {
System.out.println("索引 " + i + ": " + nums[i]);
}
// 2. 增强for循环(只读,简洁)
for (int num : nums) {
System.out.println(num);
}
// 3. while循环
int index = 0;
while (index < nums.length) {
System.out.println(nums[index++]);
}
// 4. 使用Stream API(Java 8+)
Arrays.stream(nums).forEach(System.out::println);
}
}
2.2 数组复制
public class ArrayCopy {
public static void main(String[] args) {
int[] source = {1, 2, 3, 4, 5};
// 1. System.arraycopy() - 高性能
int[] dest1 = new int[5];
System.arraycopy(source, 0, dest1, 0, source.length);
// 2. Arrays.copyOf() - 简洁
int[] dest2 = Arrays.copyOf(source, source.length);
int[] dest3 = Arrays.copyOf(source, 10); // 扩容,多余位置补0
// 3. Arrays.copyOfRange() - 复制范围
int[] dest4 = Arrays.copyOfRange(source, 1, 4); // [2, 3, 4]
// 4. clone()方法
int[] dest5 = source.clone();
// 5. 手动复制
int[] dest6 = new int[source.length];
for (int i = 0; i < source.length; i++) {
dest6[i] = source[i];
}
// 注意:浅拷贝 vs 深拷贝(对于对象数组)
Person[] persons = {new Person("Alice"), new Person("Bob")};
Person[] shallowCopy = persons.clone(); // 浅拷贝
shallowCopy[0].setName("Charlie"); // 影响原数组
}
}
三、多维数组
3.1 二维数组
public class TwoDimensionalArray {
public static void main(String[] args) {
// 1. 声明与初始化
int[][] matrix1 = new int[3][4]; // 3行4列
int[][] matrix2 = {{1,2,3}, {4,5,6}, {7,8,9}};
// 2. 不规则数组
int[][] irregular = new int[3][];
irregular[0] = new int[2];
irregular[1] = new int[3];
irregular[2] = new int[1];
// 3. 遍历二维数组
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();
}
// 4. 增强for循环遍历
for (int[] row : matrix2) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
}
}
3.2 三维及以上数组
public class MultiDimensionalArray {
public static void main(String[] args) {
// 三维数组(立方体)
int[][][] cube = new int[3][4][5];
// 初始化
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 5; k++) {
cube[i][j][k] = i + j + k;
}
}
}
// 不规则多维数组
int[][][] irregular3D = new int[2][][];
irregular3D[0] = new int[3][];
irregular3D[0][0] = new int[2];
irregular3D[0][1] = new int[1];
irregular3D[0][2] = new int[4];
}
}
四、数组与算法
4.1 排序算法实现
public class ArraySorting {
// 1. 冒泡排序
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
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;
}
}
}
}
// 2. 选择排序
public static void selectionSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
// 3. 快速排序
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high);
quickSort(arr, low, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, high);
}
}
private static int partition(int[] arr, int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, high);
return i + 1;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
4.2 查找算法
public class ArraySearch {
// 1. 线性查找
public static int linearSearch(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i;
}
}
return -1;
}
// 2. 二分查找(要求数组有序)
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
}
4.3 常见数组算法
public class ArrayAlgorithms {
// 1. 求最大值/最小值
public static int findMax(int[] arr) {
if (arr.length == 0) throw new IllegalArgumentException("数组为空");
int max = arr[0];
for (int num : arr) {
if (num > max) max = num;
}
return max;
}
// 2. 求平均值
public static double average(int[] arr) {
if (arr.length == 0) return 0;
int sum = 0;
for (int num : arr) sum += num;
return (double) sum / arr.length;
}
// 3. 数组反转
public static void reverse(int[] arr) {
int left = 0;
int right = arr.length - 1;
while (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
// 4. 删除指定元素
public static int[] removeElement(int[] arr, int target) {
int count = 0;
// 统计非目标元素个数
for (int num : arr) {
if (num != target) count++;
}
// 创建新数组
int[] result = new int[count];
int index = 0;
for (int num : arr) {
if (num != target) {
result[index++] = num;
}
}
return result;
}
}
五、Arrays 工具类
5.1 常用方法
import java.util.Arrays;
import java.util.Comparator;
public class ArraysUtils {
public static void main(String[] args) {
int[] arr = {5, 3, 8, 1, 9};
// 1. 排序
Arrays.sort(arr); // 升序排序
System.out.println(Arrays.toString(arr)); // [1, 3, 5, 8, 9]
// 2. 并行排序(大数据量性能更好)
int[] largeArr = new int[1000000];
Arrays.parallelSort(largeArr);
// 3. 二分查找
int index = Arrays.binarySearch(arr, 5); // 返回索引2
// 4. 填充数组
int[] filled = new int[5];
Arrays.fill(filled, 7); // [7, 7, 7, 7, 7]
// 5. 数组比较
int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};
boolean equal = Arrays.equals(arr1, arr2); // true
// 6. 数组转字符串
String str = Arrays.toString(arr);
// 7. 数组转列表
Integer[] boxedArr = {1, 2, 3};
List<Integer> list = Arrays.asList(boxedArr);
// 8. 流操作
int sum = Arrays.stream(arr).sum();
OptionalInt max = Arrays.stream(arr).max();
// 9. 多维数组处理
int[][] matrix = {{1,2}, {3,4}};
String deepStr = Arrays.deepToString(matrix);
boolean deepEqual = Arrays.deepEquals(matrix, new int[][]{{1,2},{3,4}});
// 10. 自定义排序
Integer[] numbers = {5, 2, 8, 1};
Arrays.sort(numbers, Comparator.reverseOrder()); // 降序排序
}
}
六、数组与集合转换
6.1 数组与List互转
import java.util.*;
public class ArrayCollectionConversion {
public static void main(String[] args) {
// 1. 数组转List
String[] array = {"A", "B", "C"};
// 方法1: Arrays.asList() - 返回固定大小列表
List<String> list1 = Arrays.asList(array);
// list1.add("D"); // 抛出UnsupportedOperationException
// 方法2: new ArrayList<>(Arrays.asList())
List<String> list2 = new ArrayList<>(Arrays.asList(array));
list2.add("D"); // 正常
// 方法3: Collections.addAll()
List<String> list3 = new ArrayList<>();
Collections.addAll(list3, array);
// 2. List转数组
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
// 方法1: toArray() - 返回Object[]
Object[] objArray = list.toArray();
// 方法2: toArray(T[]) - 推荐
String[] strArray = list.toArray(new String[0]);
String[] strArray2 = list.toArray(new String[list.size()]);
// 3. Set转数组
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
Integer[] setArray = set.toArray(new Integer[0]);
}
}
七、数组内存模型
7.1 内存分配
public class ArrayMemory {
// 数组在内存中的存储
public static void memoryDemo() {
// 栈内存存储引用,堆内存存储数组元素
int[] arr = new int[3]; // arr引用在栈中,数组对象在堆中
// 多维数组的内存结构
int[][] matrix = new int[2][3];
// matrix引用在栈中,外层数组在堆中,内层数组也在堆中
}
// 数组的内存对齐与缓存友好性
public static void cacheFriendlyDemo() {
// 连续内存访问(缓存友好)
int[][] rowMajor = new int[1000][1000];
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
rowMajor[i][j] = i + j; // 行优先访问
}
}
// 不连续内存访问(缓存不友好)
int[][] colMajor = new int[1000][1000];
for (int j = 0; j < 1000; j++) {
for (int i = 0; i < 1000; i++) {
colMajor[i][j] = i + j; // 列优先访问
}
}
}
}
八、数组高级特性
8.1 动态数组模拟
public class DynamicArray<E> {
private Object[] data;
private int size;
private static final int DEFAULT_CAPACITY = 10;
public DynamicArray() {
data = new Object[DEFAULT_CAPACITY];
size = 0;
}
// 添加元素
public void add(E element) {
ensureCapacity(size + 1);
data[size++] = element;
}
// 获取元素
@SuppressWarnings("unchecked")
public E get(int index) {
checkIndex(index);
return (E) data[index];
}
// 扩容
private void ensureCapacity(int minCapacity) {
if (minCapacity > data.length) {
int newCapacity = Math.max(data.length * 2, minCapacity);
data = Arrays.copyOf(data, newCapacity);
}
}
private void checkIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
}
public int size() {
return size;
}
}
8.2 数组与泛型
public class ArrayGenerics {
// 不能创建泛型数组
// T[] arr = new T[10]; // 编译错误
// 解决方法1:使用Object数组,然后强制转换
@SuppressWarnings("unchecked")
public static <T> T[] createGenericArray(Class<T> clazz, int size) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, size);
}
// 解决方法2:使用列表代替
public static <T> List<T> createGenericList(Class<T> clazz, int size) {
return new ArrayList<>(size);
}
// 泛型方法处理数组
public static <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
九、性能优化
9.1 数组性能技巧
public class ArrayPerformance {
// 1. 预分配大小
public static void preAllocate() {
// 不好:频繁扩容
ArrayList<Integer> list = new ArrayList<>();
// 好:预分配容量
int expectedSize = 10000;
ArrayList<Integer> optimizedList = new ArrayList<>(expectedSize);
}
// 2. 使用基本类型数组
public static void primitiveVsBoxed() {
// 不好:使用包装类型数组(内存占用大)
Integer[] boxedArray = new Integer[1000000];
// 好:使用基本类型数组
int[] primitiveArray = new int[1000000];
}
// 3. 批量复制 vs 单元素复制
public static void batchCopy() {
int[] source = new int[1000];
int[] dest = new int[1000];
// 不好:单元素复制
for (int i = 0; i < source.length; i++) {
dest[i] = source[i];
}
// 好:批量复制
System.arraycopy(source, 0, dest, 0, source.length);
}
// 4. 缓存数组长度
public static void cacheLength() {
int[] arr = new int[1000];
// 不好:每次循环都调用length
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
// 好:缓存数组长度
int len = arr.length;
for (int i = 0; i < len; i++) {
arr[i] = i;
}
}
}
十、常见应用场景
10.1 数组在实际中的应用
public class ArrayApplications {
// 1. 存储配置项
private static final String[] WEEKDAYS =
{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
// 2. 缓存最近访问记录
class LRUCache<K, V> {
private Entry<K, V>[] table;
private int capacity;
// 实现LRU缓存...
}
// 3. 矩阵运算
public static double[][] matrixMultiply(double[][] A, double[][] B) {
int rowsA = A.length;
int colsA = A[0].length;
int colsB = B[0].length;
double[][] result = new double[rowsA][colsB];
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
for (int k = 0; k < colsA; k++) {
result[i][j] += A[i][k] * B[k][j];
}
}
}
return result;
}
// 4. 游戏开发中的网格
class GameBoard {
private char[][] board;
public GameBoard(int rows, int cols) {
board = new char[rows][cols];
initializeBoard();
}
private void initializeBoard() {
for (char[] row : board) {
Arrays.fill(row, '-');
}
}
}
}
十一、最佳实践与注意事项
11.1 最佳实践
public class ArrayBestPractices {
// 1. 防御性编程
public static int sumArray(int[] arr) {
if (arr == null) {
throw new IllegalArgumentException("数组不能为null");
}
int sum = 0;
for (int num : arr) {
sum += num;
}
return sum;
}
// 2. 使用增强for循环避免越界
public static void safeIteration(int[] arr) {
// 安全:不会越界
for (int num : arr) {
System.out.println(num);
}
}
// 3. 返回空数组而非null
public static int[] getNumbers() {
// 不好:返回null
// return null;
// 好:返回空数组
return new int[0];
}
// 4. 使用System.arraycopy进行数组复制
public static int[] copyArray(int[] original) {
int[] copy = new int[original.length];
System.arraycopy(original, 0, copy, 0, original.length);
return copy;
}
}
11.2 常见陷阱
public class ArrayPitfalls {
public static void main(String[] args) {
// 陷阱1:数组越界
int[] arr = new int[5];
// arr[5] = 10; // ArrayIndexOutOfBoundsException
// 陷阱2:空指针异常
int[] nullArr = null;
// System.out.println(nullArr.length); // NullPointerException
// 陷阱3:浅拷贝
Person[] persons = {new Person("Alice")};
Person[] shallowCopy = persons.clone();
shallowCopy[0].setName("Bob"); // 原数组也被修改
// 陷阱4:数组协变性
Object[] objArray = new String[10];
objArray[0] = "Hello"; // OK
// objArray[1] = new Integer(10); // ArrayStoreException
// 陷阱5:数组大小固定
int[] fixed = new int[5];
// fixed.add(6); // 没有add方法,大小固定
// 陷阱6:多维数组的length
int[][] matrix = new int[3][4];
System.out.println(matrix.length); // 3(行数)
System.out.println(matrix[0].length); // 4(列数)
}
}
总结
关键知识点
1. 数组特点:固定大小、类型相同、连续内存、下标访问
2. 内存模型:引用在栈,数据在堆
3. 操作方式:遍历、复制、排序、查找
4. 工具类:Arrays提供丰富工具方法
5. 性能考虑:预分配、批量操作、缓存友好访问模式
选择建议
· 大小固定且类型一致 → 使用数组
· 需要动态调整大小 → 使用ArrayList
· 需要键值对 → 使用Map
· 需要去重或无序 → 使用Set
性能调优
1. 对于大量数据,使用基本类型数组而非包装类型
2. 批量操作使用System.arraycopy
3. 多维数组按行优先顺序访问
4. 合理预分配数组大小
数组是Java中最基础的数据结构,理解其特性和原理对编写高效代码至关重要。在实际开发中,根据需求选择合适的数组或集合类,并注意避免常见的陷阱。
更多推荐




所有评论(0)