← 返回题目列表

Arrays 工具类有哪些常用方法?数组和 List 怎么互相转换?

简单 第 16 / 30 题 更新于 2026/07/27
Arrays工具类数组转ListcopyOf

简化版

Arrays 是操作数组的工具类(类比 Collections 操作集合),全是静态方法。常用方法:① 排序查找sort 排序、binarySearch 二分查找、parallelSort 并行排序);② 转换asList 数组转 List、stream 数组转流);③ 复制copyOf 复制指定长度、copyOfRange 复制一段);④ 填充比较fill 填充、equals 比较、deepEquals 深度比较多维数组、toString/deepToString 打印)。数组和 List 互转是高频:数组转 ListArrays.asList(arr)(注意坑:返回定长视图、基本类型数组会变单元素)或 Arrays.stream(arr).boxed().collect(toList())List 转数组list.toArray(new String[0])

详细版

Arrays 常用方法

int[] arr = {3, 1, 2};

// ① 排序、查找
Arrays.sort(arr);                    // 排序 → [1, 2, 3](基本类型用双轴快排)
Arrays.sort(arr, 0, 2);              // 排序指定范围
int idx = Arrays.binarySearch(arr, 2);  // 二分查找(需已排序)
Arrays.parallelSort(bigArr);         // 并行排序(大数组、多核加速)

// ② 复制
int[] copy = Arrays.copyOf(arr, 5);          // 复制成长度 5(不足补 0)→ [1,2,3,0,0]
int[] range = Arrays.copyOfRange(arr, 1, 3); // 复制索引 [1,3) → [2, 3]

// ③ 填充
int[] filled = new int[3];
Arrays.fill(filled, 7);              // 全部填 7 → [7, 7, 7]

// ④ 比较、打印
Arrays.equals(arr, copy);            // 比较两个数组内容是否相等(一维)
Arrays.deepEquals(matrix1, matrix2); // 深度比较(多维数组)
Arrays.toString(arr);                // "[1, 2, 3]"(一维,别直接 arr.toString())
Arrays.deepToString(matrix);         // 多维数组打印

// ⑤ 转换
List<Integer> list = Arrays.asList(1, 2, 3);   // 转 List(有坑,见下)
IntStream stream = Arrays.stream(arr);          // 转流

数组 ⇄ List 互转

// 数组 → List
String[] strArr = {"a", "b"};
List<String> list1 = Arrays.asList(strArr);           // 定长视图(不能 add/remove,见坑)
List<String> list2 = new ArrayList<>(Arrays.asList(strArr));  // 可变的独立 List
List<String> list3 = Arrays.stream(strArr).collect(toList()); // Stream 方式

// List → 数组
List<String> list = List.of("a", "b");
String[] arr1 = list.toArray(new String[0]);          // 推荐写法
Object[] arr2 = list.toArray();                        // 返回 Object[](丢了泛型)

⚠️ Arrays.asList 有几个经典坑(前面「Arrays.asList 的坑」题详讲):① 返回定长视图add/remove 抛 UnsupportedOperationException);② 是数组的视图(改 List 会改原数组);③ 传基本类型数组会变单元素Arrays.asList(new int[]{1,2,3}) 得到 List<int[]> size=1,要用 Integer[])。要可变独立 List 用 new ArrayList<>(Arrays.asList(arr))

完整版教学

一、Arrays 是什么:操作数组的工具类

Arraysjava.util.Arrays——操作数组的静态工具类,和 Collections(操作集合)是平行的:

数组(int[]、String[]…)本身没有很多方法(不像集合有 add/remove/sort)
  数组只有 length 属性和下标访问,没有排序、查找、复制等方法
  → 需要一个工具类来提供这些操作 → Arrays

Arrays 提供的:排序、查找、复制、填充、比较、打印、转换等静态方法
用法:Arrays.sort(arr)、Arrays.copyOf(arr, n) 这样调

Arrays 弥补了「数组本身功能贫乏」的问题——数组是最底层的数据结构(连续内存、下标访问),没有集合那样丰富的方法,Arrays 工具类补上了排序、查找、复制等常用操作。它和 Collections(集合工具类)、Objects(对象工具类)是同类。理解「Arrays 是操作数组的静态工具类、补充数组的功能」,就理解了它的定位——数组的「功能扩展工具箱」。

二、排序与查找

Arrays 的排序查找是最常用的(前面「TimSort」题讲了算法,这里讲用法):

// 排序(基本类型双轴快排、对象 TimSort)
Arrays.sort(arr);                    // 整个数组排序
Arrays.sort(arr, 1, 4);              // 排序索引 [1, 4) 这一段
Arrays.sort(users, Comparator.comparing(User::getAge));  // 对象数组自定义排序

// 并行排序(大数组,利用多核)
Arrays.parallelSort(bigArr);         // 数据量大时比 sort 快(Fork/Join 并行归并)

// 二分查找(必须先排序!)
int idx = Arrays.binarySearch(arr, key);   // 找到返回下标,找不到返回负数

要点:sort 可排整个数组或指定范围sort(arr, from, to));② 对象数组要可比较或传 ComparatorparallelSort 用于大数组(多核并行,小数组反而因并行开销更慢);binarySearch 必须先排序(对未排序数组用二分查找结果不可靠,且找不到时返回 -(插入点)-1 的负数,可用于定位插入位置)。理解「Arrays.sort 排序(可指定范围)、parallelSort 并行、binarySearch 需先排序」,就掌握了 Arrays 的排序查找。

三、复制:copyOf 与 copyOfRange

Arrays 的复制方法用于「创建数组的副本」——因为数组没有内置的复制方法:

int[] arr = {1, 2, 3};

// copyOf:复制成指定长度(不足补默认值、超出截断)
int[] a = Arrays.copyOf(arr, 5);     // [1, 2, 3, 0, 0](补 0)
int[] b = Arrays.copyOf(arr, 2);     // [1, 2](截断)

// copyOfRange:复制指定范围 [from, to)
int[] c = Arrays.copyOfRange(arr, 1, 3);  // [2, 3](索引 1~2)

// 这些都是"深拷贝一维"(新数组、独立于原数组)
c[0] = 99;                           // 不影响 arr

复制方法的用途:copyOf(arr, newLength)——复制成指定长度(常用于「数组扩容」,如 ArrayList 扩容底层就用它);copyOfRange(arr, from, to)——复制一段(类似 List 的 subList 但是独立副本不是视图)。注意这些是「一维深拷贝」——对一维基本类型数组是真复制(独立);但对「对象数组」或「多维数组」是浅拷贝(只复制第一维的引用,元素对象/子数组还是共享的)。还有 System.arraycopy(更底层的复制,Arrays.copyOf 内部就用它)。理解「copyOf 复制指定长度、copyOfRange 复制一段、都是独立副本、一维深拷贝多维浅拷贝」,就掌握了数组复制。

四、比较与打印:别直接用 == 和 toString

数组的比较和打印有两个必须知道的坑——不能直接用 == 比较、不能直接 toString

int[] a = {1, 2, 3};
int[] b = {1, 2, 3};

// ✗ 直接 == 比较的是引用(地址),不是内容
a == b;                    // false(两个不同的数组对象)

// ✓ 用 Arrays.equals 比较内容
Arrays.equals(a, b);       // true(内容相同)
Arrays.deepEquals(matrix1, matrix2);  // 多维数组用 deepEquals

// ✗ 直接 toString 打印的是"类型@哈希码"
a.toString();              // "[I@1b6d3586"(没用)

// ✓ 用 Arrays.toString 打印内容
Arrays.toString(a);        // "[1, 2, 3]"
Arrays.deepToString(matrix);  // 多维数组用 deepToString

两个坑:① 比较数组内容用 Arrays.equals(数组没重写 equals,直接 ==a.equals(b) 比的是引用地址);② 打印数组内容用 Arrays.toString(数组没重写 toString,直接打印是「[I@哈希码」这种无意义的)。多维数组用 deepEquals/deepToString(递归处理每一维)。这是新手常踩的坑——想比较/打印数组内容,却用了 ==/toString。理解「数组比较内容用 Arrays.equals、打印用 Arrays.toString、多维用 deep 版本」,就避开了数组比较打印的坑。

五、数组转 List:asList 与它的坑

「数组 → List」是高频操作,主要用 Arrays.asList,但它有坑(前面详讲过,这里聚焦转换):

String[] arr = {"a", "b", "c"};

// Arrays.asList:数组转 List——但是"定长视图"
List<String> list = Arrays.asList(arr);
list.add("x");        // ✗ UnsupportedOperationException(定长,不能增删)
list.set(0, "z");     // ✓ 能改(改会同步到原数组,因为是视图)

// 要"可变的独立 List" → 包一层 ArrayList
List<String> mutable = new ArrayList<>(Arrays.asList(arr));
mutable.add("x");     // ✓ 可增删、且独立于原数组

// 基本类型数组的坑:变成单元素 List<int[]>!
int[] intArr = {1, 2, 3};
List list2 = Arrays.asList(intArr);   // ⚠️ List<int[]> size=1(整个数组当一个元素)
// 正确:用 Integer[] 或 Stream
List<Integer> list3 = Arrays.stream(intArr).boxed().collect(toList());  // ✓ size=3

三个要点:Arrays.asList 返回定长视图(不能 add/remove、且改会同步到原数组);② 要可变独立 List 用 new ArrayList<>(Arrays.asList(arr))③ 基本类型数组会被当成「一个元素」Arrays.asList(int[]) 得到 List<int[]> size=1,因为泛型不认基本类型——要用 Integer[]Arrays.stream(intArr).boxed())。理解「asList 返回定长视图、要独立用 new ArrayList、基本类型数组会变单元素」,就掌握了「数组转 List」及其坑。

六、List 转数组:toArray

「List → 数组」用 toArray,也有讲究:

List<String> list = List.of("a", "b", "c");

// 方式1:toArray()——返回 Object[](丢了泛型,要强转,不推荐)
Object[] arr1 = list.toArray();

// 方式2:toArray(T[])——返回正确类型的数组(推荐)
String[] arr2 = list.toArray(new String[0]);   // ★ 推荐写法(传长度 0 的数组)
// 传 new String[0] 而非 new String[list.size()]:
//   现代 JVM 下 new String[0] 反而更快(JIT 优化),且不用算 size,是官方推荐

// Java 11+ 新方式
String[] arr3 = list.toArray(String[]::new);   // 用构造器引用(也推荐)

要点:toArray()(无参)返回 Object[](丢了泛型,要强转成具体类型,不推荐);toArray(new String[0])(传类型数组)返回正确类型的数组(推荐——传长度 0 的空数组即可,toArray 会创建合适大小的数组,且 new String[0] 在现代 JVM 下反而比 new String[size] 快);③ Java 11+ 可用 toArray(String[]::new)(构造器引用,也推荐)。别用 toArray()(Object[] 丢泛型)。理解「List 转数组用 toArray(new T[0])(推荐)、别用无参 toArray(返回 Object[])」,就掌握了「List 转数组」的正确姿势。

记忆钩子:「Arrays 是操作数组的工具类(类比 Collections):sort 排序(可指定范围、parallelSort 并行)、binarySearch 查找(需先排序)、copyOf/copyOfRange 复制(独立副本)、fill 填充、equals 比较内容(别用 ==)、toString 打印(别直接 toString)、多维用 deepEquals/deepToString;数组转 List 用 Arrays.asList(定长视图有坑,要独立用 new ArrayList,基本类型数组会变单元素用 stream.boxed)、List 转数组用 list.toArray(new T[0])(别用无参返回 Object[])」

七、常见误区与追问

  • 误区:比较两个数组内容用 ==equals 数组没重写 equals,==a.equals(b) 比的是引用地址;比较内容要用 Arrays.equals(多维用 Arrays.deepEquals)。
  • 误区:打印数组用 arr.toString() 数组没重写 toString,直接打印是「[I@哈希码」;打印内容用 Arrays.toString(arr)(多维用 Arrays.deepToString)。
  • 误区:Arrays.asList(int[]) 得到含 3 个元素的 List。 得到 List<int[]> size=1(整个数组当一个元素,因为泛型不认基本类型);要用 Integer[]Arrays.stream(intArr).boxed().collect(toList())
  • 误区:Arrays.asList 返回可变的独立 List。 返回定长视图(不能 add/remove、改会同步到原数组);要可变独立 List 用 new ArrayList<>(Arrays.asList(arr))
  • 追问:数组怎么转 List,有什么坑?Arrays.asList(arr)(返回定长视图、改会同步原数组、基本类型数组会变单元素);要可变独立 List 用 new ArrayList<>(Arrays.asList(arr));基本类型数组用 Arrays.stream(arr).boxed().collect(toList())
  • 追问:List 怎么转数组?list.toArray(new String[0])(推荐——返回正确类型、传长度 0 的空数组即可、现代 JVM 下 new String[0] 更快)或 Java 11+ 的 list.toArray(String[]::new);别用无参 toArray()(返回 Object[]、丢泛型)。
  • 追问:Arrays.copyOf 是深拷贝还是浅拷贝? 一维基本类型数组是真复制(独立);但对象数组和多维数组是浅拷贝——只复制第一维的引用,元素对象/子数组仍共享。

八、加强记忆

Arrays 是操作数组的静态工具类(和 Collections 操作集合平行,补充数组贫乏的功能)。常用方法:① 排序查找sort 排序(可指定范围、parallelSort 大数组并行)、binarySearch 二分查找(必须先排序));② 复制copyOf(arr, n) 复制成指定长度、copyOfRange(arr, from, to) 复制一段,都是独立副本、一维深拷贝多维浅拷贝);③ 填充fill);④ 比较打印(比较内容用 Arrays.equals别用 ==,数组没重写 equals 比的是地址)、打印用 Arrays.toString别直接 toString,是「[I@哈希码」)、多维用 deepEquals/deepToString)。数组 ⇄ List 互转(高频):数组转 ListArrays.asList(arr)定长视图有坑——不能 add/remove、改会同步原数组、基本类型数组会变单元素 List<int[]>,要可变独立用 new ArrayList<>(Arrays.asList(arr))、基本类型用 Arrays.stream(arr).boxed().collect(toList()));List 转数组list.toArray(new String[0])(推荐,别用无参 toArray() 返回 Object[] 丢泛型)。一句话「Arrays 操作数组:sort/binarySearch(需先排序)/copyOf/equals(别用==)/toString(别直接)、多维用 deep 版;数组转 List 用 asList(定长视图有坑)、List 转数组用 toArray(new T[0])」。