当前位置: 首页 > news >正文

【Java SE】Arrays工具类

本章将介绍Arrays工具类中的常用方法,主要是操作数组的一些方法。

 1.为什么需要学习Arrays工具类

在Java中我们定义一个数组,那么对这个数组的增删改查是不是都需要写相应的方法去实现呢?答案是不需要,因为Java将操作数组的方法封装在了Arrays工具类中,该类在java.util 包中,我们对数组的操作我们只需要导入这个类调用其方法即可。

对比项原始数组使用 Arrays 类
排序需手动实现排序算法Arrays.sort(arr)
查找需遍历或自己写二分查找Arrays.binarySearch(arr, key)
复制需用 for 循环手动复制Arrays.copyOf(arr)
比较需逐个元素比较Arrays.equals(arr1, arr2)
打印直接打印得到内存地址Arrays.toString(arr) 显示内容
填充需写循环赋值Arrays.fill(arr, value)

2.Arrays工具类的本质和核心思想 

本质:

Arrays 是 Java 专门为操作数组设计的工具类(utility class),它:

  1. 📦 封装数组操作:将开发者常用的数组操作封装成静态方法

  2. ⚙️ 避免重复造轮子:开发者不需要手动实现基础数组算法

  3. 🚀 提供高性能实现:底层使用优化过的算法(如双轴快速排序)

  4. 🧩 补充数组功能:弥补 Java 数组原生功能不足的缺陷

核心:

    静态方法工具类

  • 所有方法都是 static 的

  • 不需要实例化(构造函数私有化)

  • 直接通过类名调用:Arrays.方法名(参数);

3.Arrays中有哪些方法?

在学习Arrays的时候需要查看Java API帮助文档来学习,具体的方法不需要背,多查多用不断地重复自然就记住了,具体的API文档链接如下:

  • Java 21 APIhttps://docs.oracle.com/en/java/javase/21/docs/api/

  • Java 17 APIhttps://docs.oracle.com/en/java/javase/17/docs/api/

  • Java 11 APIhttps://docs.oracle.com/en/java/javase/11/docs/api/

  • Java 8 APIhttps://docs.oracle.com/javase/8/docs/api/

以下是 java.util.Arrays 类中所有核心方法的分类表格总结(基于 Java 17):

一、数组操作核心方法

方法签名作用示例
static void sort(primitive[] a)对基本类型数组升序排序Arrays.sort(new int[]{3,1,2}) → [1,2,3]
static void sort(Object[] a)对对象数组按自然顺序排序Arrays.sort(new String[]{"c","a","b"}) → ["a","b","c"]
static void sort(T[] a, Comparator<? super T> c)自定义比较器排序Arrays.sort(users, Comparator.comparing(User::age))
static int binarySearch(primitive[] a, primitive key)二分查找基本类型数组Arrays.binarySearch(new int[]{1,2,3}, 2) → 1
static int binarySearch(T[] a, T key, Comparator<? super T> c)带比较器的二分查找Arrays.binarySearch(users, keyUser, Comparator.comparing(User::id))
static boolean[] copyOf(boolean[] original, int newLength)复制数组并调整长度Arrays.copyOf(new int[]{1,2}, 3) → [1,2,0]
static T[] copyOf(T[] original, int newLength)复制对象数组Arrays.copyOf(names, names.length * 2)
static void fill(primitive[] a, primitive val)填充整个数组Arrays.fill(arr, -1) → [-1,-1,-1]
static void fill(Object[] a, Object val)填充对象数组Arrays.fill(strArr, "empty")
static void fill(primitive[] a, int from, int to, primitive val)填充指定范围Arrays.fill(arr, 1, 3, 9) → [0,9,9,0]

二、数组比较与哈希

方法签名作用说明
static boolean equals(primitive[] a, primitive[] b)比较基本类型数组长度和元素值全等
static boolean equals(Object[] a, Object[] b)比较对象数组调用每个元素的 equals()
static boolean deepEquals(Object[] a, Object[] b)深度比较多维数组递归比较嵌套数组
static int hashCode(primitive[] a)计算数组哈希值基于内容
static int deepHashCode(Object[] a)深度计算哈希值适用于嵌套数组

三、数组转字符串

方法签名作用示例输出
static String toString(primitive[] a)一维数组转字符串"[1, 2, 3]"
static String toString(Object[] a)对象数组转字符串"[A, B, C]"
static String deepToString(Object[] a)多维数组深度转字符串"[[1, 2], [3, 4]]"

四、Java 8+ 新增方法

方法签名作用场景
static void parallelSort(primitive[] a)并行排序(多核)大数据量排序
static <T> void parallelSort(T[] a, Comparator<? super T> cmp)并行对象排序
static void parallelPrefix(primitive[] array, PrimitiveBinaryOperator op)并行计算前缀[1,2,3] → [1,3,6](累加)
static void setAll(int[] array, IntUnaryOperator generator)函数式生成元素setAll(arr, i -> i*2)
static <T> Spliterator<T> spliterator(T[] array)获取分割迭代器流式处理基础
static IntStream stream(int[] array)生成IntStream流Arrays.stream(arr).sum()
static <T> Stream<T> stream(T[] array)生成对象Stream流Arrays.stream(users).filter(u->u.age>18)

五、特殊操作

方法签名作用说明
static List<T> asList(T... a)数组转固定大小List注意: 返回的List不支持增删操作
static void parallelSetAll(primitive[] array, IntFunction generator)并行生成元素Java 8+
static int mismatch(primitive[] a, primitive[] b)查找首个不匹配索引全等返回-1
static int compare(primitive[] a, primitive[] b)字典序比较数组类似 String.compareTo()

六、多维数组专用

方法签名作用替代方案
static int deepHashCode(Object[] a)深度哈希计算替代手动嵌套循环
static boolean deepEquals(Object[] a, Object[] b)深度比较替代手动嵌套循环
static String deepToString(Object[] a)深度转字符串替代 Arrays.toString() 的嵌套调用

📌 关键说明:

  1. primitive 代表 8 种基本类型:byte/short/int/long/float/double/char/boolean

  2. T 代表引用类型(对象)

  3. 并行方法(如 parallelSort)适合处理超过 100 万元素的大型数组

  4. 流式方法(如 stream())需配合 Java 8+ 的 Stream API 使用

  5. asList()陷阱:返回的 ArrayList 是 Arrays 内部类,非 java.util.ArrayList

4.Arrays中常用方法 

以下是 Arrays 工具类中常见方法的表格总结及作用说明:

方法名作用描述典型使用场景
binarySearch()已排序的数组中二分查找指定元素,返回索引(找到时)或负数(未找到时)快速查找有序数组中的元素(时间复杂度 O(log n))
copyOf()复制原数组并截断或填充到指定长度(新数组长度可大于/小于原数组)数组扩容、缩容或创建副本
equals()比较两个一维数组是否内容相等(长度相同且对应位置元素相等)判断简单数组(非嵌套)是否内容一致
fill()将指定值填充到数组的所有位置(或指定范围)数组初始化(如全置0)或重置内容
sort()对数组进行升序排序(支持基本类型/对象类型),可指定范围或自定义比较规则数组排序(时间复杂度 O(n log n))
toString()返回一维数组的字符串表示(如 [1, 2, 3]),不处理嵌套数组快速打印一维数组内容(调试输出)
deepToString()返回多维数组的深层内容字符串(递归处理嵌套数组)打印多维数组(如 int[][])的实际内容

1.将一维数组转为字符串

Arrays.toString(待操作数组名)

解释:将指定一维数组转为字符串

import java.util.Arrays;public class ArraysToString {public static void main(String[] args) {//定义一个数组int[] arr = {1, 2, 3, 4, 5};//将数组转为字符串并输出String str = Arrays.toString(arr);System.out.println(str);System.out.println("=============");System.out.println(Arrays.toString(arr));}
}

2.将二维数组转为字符串

Arrays.deepToString(待操作数组名)

解释:将指定二维数组转为字符串,deep代表深度,说明是将多维数组转为字符串

import java.util.Arrays;public class ArraysDeepToString {public static void main(String[] args) {//定义一个二维数组int[][] arrs = {{1,2,3}, {4,5,6,7}, {8,9,10,11,12}};//将二维数组转为字符串并输出System.out.println(Arrays.deepToString(arrs));}
}

3.对数组进行排序

Arrays.sort(待操作数组名)

解释:将待操作数组进行小到大排序

import java.util.Arrays;public class ArraysSort {public static void main(String[] args) {//定义一个数组int[] arr = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};System.out.println("排序前:" + Arrays.toString(arr));//使用Arrays中的sort()方法默认是从小到大排序Arrays.sort(arr);System.out.println("排序后:" + Arrays.toString(arr));}
}

4. 在已排序的数组中使用二分查找某个元素

Arrays.binarySearch(待查询数组名,所要查找的值); 

Arrays.binarySearch(arr,key);

解释:在arr数组中使用二分查找找出key值如果找到就将他的下标返回

import java.util.Arrays;public class ArraysBinarySearch {public static void main(String[] args) {//定义一个数组int[] arr = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};System.out.println("排序前:" + Arrays.toString(arr));//[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]//使用Arrays中的sort()方法默认是从小到大排序Arrays.sort(arr);System.out.println("排序后:" + Arrays.toString(arr));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]//使用二分查找找出元素8int tmp = Arrays.binarySearch(arr,8);System.out.println("查找出后的值的索引为:" + tmp);}
}

5.两个数组中内容的比较                

        使用的是Arrays.equals方法

        反正你记住:比较内容使用的都是equals方法

public class ArraysEquals {public static void main(String[] args){int[] arr1 = {1, 2, 3, 4, 5};int[] arr2 = {1, 2, 3, 4, 5};int[] arr3 = {10, 2, 3, 4, 5};System.out.println(Arrays.equals(arr1, arr2));//trueSystem.out.println(Arrays.equals(arr1, arr3));//falseSystem.out.println(Arrays.equals(arr2, arr3));//false}
}

6.在数组中填充给定的值

        使用的是Arrays.fill方法。

        fill是充满的意思,在Arrays中改方法用于当不知道或者不想手动对数组赋初值的时候就使用该方法。

public class ArraysFill {public static void main(String[] args) {int[] arr = new int[10];//将arr所有位置填充10Arrays.fill(arr, 10);System.out.println(Arrays.toString(arr));//[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]//将arr[3, 7)的位置填充上100 实际填充的位置是3,4,5,6  顾前不顾后Arrays.fill(arr, 3, 7, 100);System.out.println(Arrays.toString(arr));//[10, 10, 10, 100, 100, 100, 100, 10, 10, 10]//                                          0    1   2   3    4    5   6    7    8  9}

7.拷贝数组

7.1 自定义拷贝数组

        什么是拷贝? 所谓的拷贝就是对照着arr数组进行一模一样的复刻从而产生arr长得一模一样的数组copy。

        拷贝一定是产生一个新对象的,也就是说必须是重新new一个新数组的。

public class ArraysCopyOf01 {/*** 首先 搞清楚什么是拷贝:*  所谓的拷贝(复制)*   就是说将一个东西 原模原样的复制出新的一份来,那么他必须是产生了新的实体的*   所以拷贝自然是需要new出一个新的对象的* @param args*/public static void main(String[] args) {//定义一个数组int[] arr = {1, 2, 3, 35, 45};//将拷贝之前的数组arr内容输出for (int i: arr) {System.out.print(i + " ");}System.out.println();//对arr这个数组进行拷贝int[] copy = new int[arr.length];//将arr里面数据进行复制在copy中for (int i = 0; i < arr.length; i++) {copy[i] = arr[i];}//将拷贝后的数组copy内容输出for (int i: copy) {System.out.print(i + " ");}System.out.println();}
}

 拷贝后的数组的内存图如下:

注意:以下的情况不属于拷贝, 而是属于赋值

public class ArraysCopyOfTest {public static void main(String[] args) {//以下情况属于的是赋值,而不是拷贝//定义一个数组int[] arr = {1, 2, 3, 35, 45};//将arr对象的地址赋值给copy变量存起来int[] copy = arr;}
}

7.2 Arrays.copyOf

数组的拷贝java已经给我们封装好了,拷贝数组的这个方法已经封装在Arrays工具类中了

解释:

         Arrays.copyOf(对哪一个数组进行拷贝,拷贝多长);

        他的返回值是一个新的数组的,我们到时候使用一个copy数组接收就OK了。

代码如下:

public class ArraysCopyOf02 {public static void main(String[] args) {//定义一个数组int[] arr = {1, 2, 3, 35, 45};//定义一个数字变量 到时候用于接收返回值int[] copy;//对arr数组进行拷贝并且将返回的数组对象地址使用copy接收copy = Arrays.copyOf(arr, arr.length);//打印System.out.println(Arrays.toString(copy));//[1, 2, 3, 35, 45]}
}

copyOf的底层代码分析:

 7.3 Arrays.copyOfRange

        解释:

                copyOfRange 首先Range这个单词是范围的意思,那么顾名思义就是说:这个方法就是对数组进行范围式的拷贝

                Arrays.copyOfRange(要拷贝的数组,起点,终点)。

                其中:起点和终点是下标 遵循左闭右开原则[起点,终点)(顾前不顾后)

public class ArraysCopyOf03 {public static void main(String[] args) {//定义一个数组int[] arr = {1, 2, 3, 35, 45};//           0  1  2  3   4//定义一个数字变量 到时候用于接收返回值int[] copy;//对arr数组进行拷贝[1,4)并且将返回的数组对象地址使用copy接收copy = Arrays.copyOfRange(arr, 1, 4);//打印System.out.println(Arrays.toString(copy));//[2, 3, 35]}
}

 copyOfRange底层也是调用了System.arraycopy方法,那么对于该方法的解析是什么呢,请继续往后面看

 7.4 System.arraycopy

代码:

public class ArraysCopyOf04 {public static void main(String[] args) {// 定义一个数组int[] arr = {1, 2, 3, 35, 45};//           0  1  2  3   4//定义一个copy数组用于存储拷贝后的数据int[] copy = new int[arr.length];//使用System.arraycopy进行数组的拷贝System.arraycopy(arr, 0, copy, 0, arr.length);System.out.println(Arrays.toString(arr));//拷贝前arr数组 [1, 2, 3, 35, 45]System.out.println(Arrays.toString(copy));//拷贝前copy数组 [1, 2, 3, 35, 45]}
}

 对该方法的解析

例如:

 补充:结合前面所介绍的,数组的拷贝使用Arrays.copyOf和使用System.arraycopy的效率问题:结论是使用System.arraycopy的效率会高一点,原因就是说,由于Arrays.copy底层也是调用System.arraycopy,因此呢,自然没有你直接使用System.arraycopy来得快,当然,现在的话,我是不去纠结该使用哪一个比较好的,他们的效率其实是近似的,二者是差不多的,具体你想使用哪一个方法扩容根据你的需求去处理即可。

7.5 由拷贝引申出的扩容问题 

        首先什么是扩容?==》扩容有两个特点:将容量变大 和 将原来的数据搬运进去(拷贝进去)。

        代码:

public class CopyOfDilatation {public static void main(String[] args) {//定义一个arr数组int[] arr = {1, 3, 4, 7, 10};//首先将对arr进行拷贝int[] copy = Arrays.copyOf(arr, arr.length*2);//最后将copy所指向的地址给arr 从而实现扩容arr = copy;//将arr打印System.out.println(Arrays.toString(arr));//[1, 3, 4, 7, 10, 0, 0, 0, 0, 0]}

细节分析:

内存图如下:
 

http://www.xdnf.cn/news/1089649.html

相关文章:

  • OpenCV哈希算法------Marr-Hildreth 边缘检测哈希算法
  • 字符串大小比较的方式|函数的多返回值
  • Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
  • 【DOCKER】-2 docker基础
  • 车载以太网-TC8测试-UT(Upper Tester)
  • 基于物联网的智能交通灯控制系统设计
  • RAGflow图像解析与向量化分析
  • 基于模板设计模式开发优惠券推送功能以及对过期优惠卷进行定时清理
  • 文献学习|全面绘制和建模水稻调控组景观揭示了复杂性状背后的调控架构。
  • 【洛谷题单】--顺序结构(一)
  • MyBatis-Plus:深入探索与最佳实践
  • 《UE5_C++多人TPS完整教程》学习笔记42 ——《P43 瞄准(Aiming)》
  • 【Linux服务器】-安装ftp与sftp服务
  • JavaScript基础篇——第二章 类型转换与常见错误解析
  • openEuler2203sp4-vg磁盘组中剔除磁盘
  • 11款常用C++在线编译与运行平台推荐与对比
  • 【PyTorch】PyTorch中torch.nn模块的激活函数
  • 初识mysql(一)
  • Spring Bean 的生命周期
  • Python入门Day5
  • 数据结构*搜索树
  • CI/CD — DevOps概念之实现k8s持续交付持续集成(一)
  • Maven 打包排除特定依赖的完整指南(详细方法 + 示例)
  • -温差双八无碳小车cad【14张】+三维图+设计说明书+总装配图+绛重
  • 高版本的MacOS如何降级?
  • Qt:图片切割
  • numpy数据分析知识总结
  • 使用Node.js搭建Web应用有哪些注意事项?
  • LocalStorage和SessionStorage的区别和应用
  • 零基础 Qt 6 在线安装教程