日常开发中,我们会使用各种工具类,利用封装好的轮子,能让我们的开发事半功倍。但是在jdk中,有一个特别的工具类——java.lang.arrays.class,其源码实现还是挺精湛,接下来让我们来揭开它神秘的面纱。
java.util.arrays 类是 jdk 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本上都是静态方法,能直接通过类名arrays调用。
1、aslistpublic static list aslist(t... a) { return new arraylist(a); }作用是返回由指定数组支持的固定大小列表。
注意 :这个方法返回的 arraylist 不是我们常用的集合类 java.util.arraylist。这里的 arraylist 是 arrays 的一个内部类 java.util.arrays.arraylist。这个内部类有如下属性和方法:
private static class arraylist extends abstractlist implements randomaccess, java.io.serializable{ private static final long serialversionuid = -2764017481108945198l; private final e[] a; arraylist(e[] array) { if (array==null){ throw new nullpointerexception(); } a = array; } public int size() { return a.length; } public object[] toarray() { return a.clone(); } public t[] toarray(t[] a) { int size = size(); if (a.length < size){ return arrays.copyof(this.a, size,(class) a.getclass()); } system.arraycopy(this.a, 0, a, 0, size); if (a.length > size){ a[size] = null; } return a; } public e get(int index) { return a[index]; } public e set(int index, e element) { e oldvalue = a[index]; a[index] = element; return oldvalue; } public int indexof(object o) { if (o==null) { for (int i=0; i< a.length; i++){ if (a[i]==null){ return i; } } } else { for (int i=0; i< a.length; i++){ if (o.equals(a[i])){ return i; } } } return -1; } public boolean contains(object o) { return indexof(o) != -1; }}①、返回的 arraylist 数组是一个定长列表,我们只能对其进行查看或者修改,但是不能进行添加或者删除操作
通过源码我们发现该类是没有add()或者remove() 这样的方法的,如果对其进行增加或者删除操作,都会调用其父类 abstractlist 对应的方法,而追溯父类的方法最终会抛出 unsupportedoperationexception 异常。如下:
string[] str = {a,b,c}; list liststr = arrays.aslist(str); liststr.set(1, e);//可以进行修改 system.out.println(liststr.tostring());//[a, e, c] liststr.add(a);//添加元素会报错 java.lang.unsupportedoperationexception
②、引用类型的数组和基本类型的数组区别
string[] str = {a,b,c};list liststr = arrays.aslist(str);system.out.println(liststr.size());//3int[] i = {1,2,3};list listi = arrays.aslist(i);system.out.println(listi.size());//1上面的结果第一个liststr.size()==3,而第二个 listi.size()==1。这是为什么呢?
我们看源码,在 arrays.aslist 中,方法声明为listaslist(t... a)。该方法接收一个可变参数,并且这个可变参数类型是作为泛型的参数。我们知道基本数据类型是不能作为泛型的参数的,但是数组是引用类型,所以数组是可以泛型化的,于是 int[] 作为了整个参数类型,而不是 int 作为参数类型。
所以将上面的方法泛型化补全应该是:
string[] str = {a,b,c};list liststr = arrays.aslist(str);system.out.println(liststr.size());//3int[] i = {1,2,3};list listi = arrays.aslist(i);//注意这里list参数为 int[] ,而不是 intsystem.out.println(listi.size());//1integer[] in = {1,2,3};list listin = arrays.aslist(in);//这里参数为int的包装类integer,所以集合长度为3system.out.println(listin.size());//3③、返回的列表arraylist里面的元素都是引用,不是独立出来的对象
string[] str = {a,b,c};list liststr = arrays.aslist(str);//执行更新操作前system.out.println(arrays.tostring(str));//[a, b, c]liststr.set(0, d);//将第一个元素a改为d//执行更新操作后system.out.println(arrays.tostring(str));//[d, b, c]这里的arrays.tostring()方法就是打印数组的内容,后面会介绍。我们看修改集合的内容,原数组的内容也变化了,所以这里传入的是引用类型。
④、已知数组数据,如何快速获取一个可进行增删改查的列表list?
string[] str = {a,b,c}; list liststr = new arraylist(arrays.aslist(str)); liststr.add(d); system.out.println(liststr.size());//4这里的arraylist 集合类后面我们会详细讲解,大家目前只需要知道有这种用法即可。
⑤、arrays.aslist() 方法使用场景
arrays工具类提供了一个方法aslist, 使用该方法可以将一个变长参数或者数组转换成list 。但是,生成的list的长度是固定的;能够进行修改操作(比如,修改某个位置的元素);不能执行影响长度的操作(如add、remove等操作),否则会抛出unsupportedoperationexception异常。
所以 arrays.aslist 比较适合那些已经有数组数据或者一些元素,而需要快速构建一个list,只用于读取操作,而不进行添加或删除操作的场景。
2、sort该方法是用于数组排序,在 arrays 类中有该方法的一系列重载方法,能对7种基本数据类型,包括 byte,char,double,float,int,long,short 等都能进行排序,还有 object 类型(实现了comparable接口),以及比较器 comparator 。
①、基本类型的数组
这里我们以 int[ ] 为例看看:
int[] num = {1,3,8,5,2,4,6,7}; arrays.sort(num); system.out.println(arrays.tostring(num));//[1, 2, 3, 4, 5, 6, 7, 8]通过调用 sort(int[] a) 方法,将原数组按照升序的顺序排列。下面我们通过源码看看是如何实现排序的:
public static void sort(int[] a) { dualpivotquicksort.sort(a, 0, a.length - 1, null, 0, 0); }在 arrays.sort 方法内部调用 dualpivotquicksort.sort 方法,这个方法的源码很长,分别对于数组的长度进行了各种算法的划分,包括快速排序,插入排序,冒泡排序都有使用。详细源码可以参考这篇博客。
②、对象类型数组
该类型的数组进行排序可以实现 comparable 接口,重写 compareto 方法进行排序。
string[] str = {a,f,c,d}; arrays.sort(str); system.out.println(arrays.tostring(str));//[a, c, d, f]string 类型实现了 comparable 接口,内部的 compareto 方法是按照字典码进行比较的。
③、没有实现comparable接口的,可以通过comparator实现排序
person[] p = new person[]{new person(zhangsan,22),new person(wangwu,11),new person(lisi,33)};arrays.sort(p,new comparator() { @override public int compare(person o1, person o2) { if(o1 == null || o2 == null){ return 0; } return o1.getpage()-o2.getpage(); }}); system.out.println(arrays.tostring(p));3、binarysearch用二分法查找数组中的某个元素。该方法和 sort 方法一样,适用于各种基本数据类型以及对象。
注意:二分法是对以及有序的数组进行查找(比如先用arrays.sort()进行排序,然后调用此方法进行查找)。找到元素返回下标,没有则返回 -1
实例:
int[] num = {1,3,8,5,2,4,6,7}; arrays.sort(num); system.out.println(arrays.tostring(num));//[1, 2, 3, 4, 5, 6, 7, 8] system.out.println(arrays.binarysearch(num, 2));//返回元素的下标 1具体源码实现:
public static int binarysearch(int[] a, int key) { return binarysearch0(a, 0, a.length, key); } private static int binarysearch0(int[] a, int fromindex, int toindex,int key) { int low = fromindex; int high = toindex - 1; while (low >> 1;//取中间值下标 int midval = a[mid];//取中间值 if (midval key) high = mid - 1; } else{ return mid; } } return -(low + 1); }4、copyof拷贝数组元素。底层采用 system.arraycopy() 实现,这是一个native方法。
public static native void arraycopy(object src, int srcpos, object dest, int destpos, int length);src:源数组
srcpos:源数组要复制的起始位置
dest:目的数组
destpos:目的数组放置的起始位置
length:复制的长度
注意:src 和 dest都必须是同类型或者可以进行转换类型的数组。
int[] num1 = {1,2,3};int[] num2 = new int[3];system.arraycopy(num1, 0, num2, 0, num1.length);system.out.println(arrays.tostring(num2));//[1, 2, 3]/** * @param original 源数组 * @param newlength //返回新数组的长度 * @return */ public static int[] copyof(int[] original, int newlength) { int[] copy = new int[newlength]; system.arraycopy(original, 0, copy, 0, math.min(original.length, newlength)); return copy; }5、fill该系列方法用于给数组赋值,并能指定某个范围赋值。
//给a数组所有元素赋值 val public static void fill(int[] a, int val) { for (int i = 0, len = a.length; i < len; i++){ a[i] = val; } } //给从 fromindex 开始的下标,toindex-1结尾的下标都赋值 val,左闭右开 public static void fill(int[] a, int fromindex, int toindex, int val) { rangecheck(a.length, fromindex, toindex);//判断范围是否合理 for (int i = fromindex; i < toindex; i++){ a[i] = val; } }6、tostring 和 deeptostringtostring 用来打印一维数组的元素,而 deeptostring 用来打印多层次嵌套的数组元素。
public static string tostring(int[] a) { if (a == null){ return null; } int imax = a.length - 1; if (imax == -1){ return []; } stringbuilder b = new stringbuilder(); b.append('['); for (int i = 0; ; i++) { b.append(a[i]); if (i == imax){ return b.append(']').tostring(); } b.append(, ); } }7、小结好了,这就是jdk中java.lang.arrays 类的源码解析。
人工智能赋能机器视觉 让3D视觉无所不在
如果是多通道输入数据,是否依然存在矩阵乘法呢?
紫光展锐CEO任奇伟:用 “芯” 助力5G改变社会
新能源汽车需要摇号吗_新能源汽车怎么摇号_新能源汽车摇号规则
磁性材料厂家知多少:国内外磁性材料厂家整理
JDK中java.lang.Arrays 类的源码解析
道尔芬智能在第八届“创客中国”暨2023江苏省中小企业创新创业大赛中喜获优秀项目奖并成功晋级省专题赛
耦合器使用中的常见故障有哪些?
LCD与OLED对比差距到底有多大?
大立光成为全球光学产业最神秘的黑匣子
燃料电池组件的模块化方法,可降低电池制造成本
使用高频超声波的半导体单片清洗中的微粒子去除研究
航班管家荣获阿拉丁神灯奖“小程序行业最佳工具奖”
传AMD已开发两款ARM原型处理器,欲与苹果M1竞争
5G进入射频前端技术的发展前景分析
瑞萨电子推出多功能气体传感方案
为何汽车需要48V电压系统
常见的计算机病毒
海林投资:硬科技成投资主赛道 资本如何打破同质化竞争怪圈
肖特基二极管是什么?肖特基二极管常见型号与作用