详解Java合并数组的两种实现方式
最近在写代码时遇到了需要合并两个数组的需求,突然发现以前没用过,于是研究了一下合并数组的方式,总结如下。
1.System.arraycopy()方法
(1)解析
通过阅读JDK源码,我可以知道方法原型如下:
publicstaticnativevoidarraycopy(Objectsrc,intsrcPos,Objectdest,intdestPos,intlength);
其中:
src是源数组
srcPos是源数组复制的起始位置
dest是目标数组
destPos是目标数组接收复制数据的起始位置
length是复制的长度(源数组中从复制起始位置srcPos开始需要复制的长度)
可以看到,该方法是本地方法,我们不能更深一步的了解其中的原理,但是我们可以知道其作用就是将源数组从起始位置srcPos开始将length长度的元素复制到目标数组,目标数组从destPos位置开始接收复制元素。
(2)示例
String[]aa={"11","22","33"}; String[]bb={"44","55","66"}; String[]cc={"77","88","99"}; //合并两个数组 String[]dd=newString[aa.length+bb.length]; System.arraycopy(aa,0,dd,0,aa.length); System.arraycopy(bb,0,dd,aa.length,bb.length); //合并三个数组 String[]ee=newString[aa.length+bb.length+cc.length]; System.arraycopy(aa,0,ee,0,aa.length); System.arraycopy(bb,0,ee,aa.length,bb.length); System.arraycopy(cc,0,ee,aa.length+bb.length,cc.length);
2.ArrayUtils.addAll()方法
(1)解析
ArrayUtils工具类在apachecommons-lang3-3.5中的commons-lang3-3.5.jar(jar包下载地址)中,所以使用之前需要导入这个包。通过阅读其源码,我们可以发现,其实addAll()方法本质上还是调用System.arraycopy()方法。
publicstaticT[]addAll(finalT[]array1,finalT...array2){ if(array1==null){ returnclone(array2); }elseif(array2==null){ returnclone(array1); } finalClass>type1=array1.getClass().getComponentType(); @SuppressWarnings("unchecked")//OK,becausearrayisoftypeT final //a处 T[]joinedArray=(T[])Array.newInstance(type1,array1.length+array2.length); System.arraycopy(array1,0,joinedArray,0,array1.length); try{ //b处 System.arraycopy(array2,0,joinedArray,array1.length,array2.length); }catch(finalArrayStoreExceptionase){ //Checkifproblemwasduetoincompatibletypes /* *Wedothishere,ratherthanbeforethecopybecause: *-itwouldbeawastedcheckmostofthetime *-safer,incasecheckturnsouttobetoostrict */ finalClass>type2=array2.getClass().getComponentType(); if(!type1.isAssignableFrom(type2)){ thrownewIllegalArgumentException("Cannotstore"+type2.getName()+"inanarrayof" +type1.getName(),ase); } throwase;//No,sorethroworiginal } returnjoinedArray; }
这个方法关键的两个部分就是代码中标注的a、b两处。a处首先通过反射的方式定义了一个长度为array1、array2长度之和的数组joinedArray,然后将array1拷贝到joinedArray,b处将array2拷贝到joinedArray中。除了这两处,还有异常处理需要注意,在捕获异常后,判断了type1是不是继承于type2,也就是判断array1所对应的类型是否与array2对应类型相同,或者array1所对应的类型是否是array2对应类型的子类,否则将出现不兼容的情况。
(2)示例
//合并两个数组 String[]ff=ArrayUtils.addAll(aa,bb); //将多个字符串合并到数组构成新数组 String[]gg=ArrayUtils.addAll(aa,"12","13"); String[]hh=ArrayUtils.addAll(aa,"12","13","14"); String[]ii=ArrayUtils.addAll(aa,"12","13","14","15"); //合并三个数组 String[]jj=ArrayUtils.addAll(aa,bb); String[]kk=ArrayUtils.addAll(jj,cc);
需要说明的是,addAll()的第二个参数是可变参数,可以传入多个相同类型的值,或者一个该类型的数组。
(3)错误处理
我在使用过程中遇到一个问题,具体如下:
代码1:
String[]ll=ArrayUtils.addAll(aa,bb,cc);
根据提示发现,addAll()返回值类型是Serializable[],所有不能喝String[]兼容。于是我将代码改成如下代码:
代码2:
ArrayUtils.addAll(aa,bb,cc);
我以为不接收返回值只是合并就不会报错了,虽然通过了编译,但是运行还是报错了。错误信息如下:
Exceptioninthread"main"java.lang.IllegalArgumentException:Cannotstorejava.io.Serializableinanarrayofjava.lang.String atorg.apache.commons.lang3.ArrayUtils.addAll(ArrayUtils.java:5084) atcom.liu.date20170524.MergeArrays.main(MergeArrays.java:44) Causedby:java.lang.ArrayStoreException atjava.lang.System.arraycopy(NativeMethod) atorg.apache.commons.lang3.ArrayUtils.addAll(ArrayUtils.java:5073) ...1more
由于当时陷入了惯性思维,认为addAll和List等的addAll()方法类型,可以将多个列表(这里是数组)进行合并,所以一直没想明白错误出在哪里。后来才发现,addAll()的第二个参数的类型是T,不是T[],所以不能合并两个以上的数组。望各位引以为戒。
参考:https://www.nhooo.com/article/129962.htm
以上所述是小编给大家介绍的Java合并数组的两种实现方式详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!