详解Java合并数组的两种实现⽅式
最近在写代码时遇到了需要合并两个数组的需求,突然发现以前没⽤过,于是研究了⼀下合并数组的⽅式,总结如下。1.System.arraycopy()⽅法
(1) 解析
通过阅读JDK源码,我可以知道⽅法原型如下:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
其中:
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 = new String[aa.length + bb.length];
System.arraycopy(aa, 0, dd, 0, aa.length);
System.arraycopy(bb, 0, dd, aa.length, bb.length);
// 合并三个数组
String[] ee = new String[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⼯具类在apache commons-lang3-3.5中的commons-lang3-3.5.jar(jar包下载地址)中,所以使⽤之前需要导⼊这个包。通过阅读其源码,我们可以发现,其实addAll()⽅法本质上还是调⽤System.arraycopy()⽅法。
public static <T> T[] addAll(final T[] array1, array2) {
if (array1 == null) {
return clone(array2);
} else if (array2 == null) {
return clone(array1);
}
final Class<?> type1 = Class().getComponentType();
@SuppressWarnings("unchecked") // OK, because array is of type T
final
// a处
T[] joinedArray = (T[]) wInstance(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 (final ArrayStoreException ase) {
// Check if problem was due to incompatible types
/*
* We do this here, rather than before the copy because:
* - it would be a wasted check most of the time
* - safer, in case check turns out to be too strict
*/
final Class<?> type2 = Class().getComponentType();
if (!type1.isAssignableFrom(type2)) {
throw new IllegalArgumentException("Cannot store " + Name() + " in an array of "
+ Name(), ase);
}
throw ase; // No, so rethrow original
}
return joinedArray;
}
这个⽅法关键的两个部分就是代码中标注的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);
springboot其实就是spring我以为不接收返回值只是合并就不会报错了,虽然通过了编译,但是运⾏还是报错了。错误信息如下:
Exception in thread "main" java.lang.IllegalArgumentException: Cannot store java.io.Serializable in an array of java.lang.String
at org.apachemons.lang3.ArrayUtils.addAll(ArrayUtils.java:5084)
at com.liu.date20170524.MergeArrays.main(MergeArrays.java:44)
Caused by: java.lang.ArrayStoreException
at java.lang.System.arraycopy(Native Method)
at org.apachemons.lang3.ArrayUtils.addAll(ArrayUtils.java:5073)
... 1 more
由于当时陷⼊了惯性思维,认为addAll和List等的addAll()⽅法类型,可以将多个列表(这⾥是数组)进⾏合并,所以⼀直没想明⽩错误出在哪⾥。后来才发现,addAll()的第⼆个参数的类型是T,不是T[],所以不能合并两个以上的数组。望各位引以为戒。
以上所述是⼩编给⼤家介绍的Java合并数组的两种实现⽅式详解整合,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。在此也⾮常感谢⼤家对⽹站的⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。