数组复制,扩容的几个容易搞混的方法
几个数组方法搞的我头晕, 记不住,就直接写下来了。
1、 先来一个底层方法:
System.arraycory(源数组,源数组开始位置,目标数组,目标数组开始位置, 复制的长度)
*这个方法,每次看着看着就有晕了过去,参数太多,类型又差不多,总是会看偏,理解错。 其实,System类的源码,解释的还是很清楚的*
源码+注释:
/** * @param src the source array. 源数组 * @param srcPos starting position in the source array. 源数组复制的开始位置 * @param dest the destination array. 目标数组 * @param destPos starting position in the destination data. 目标数组接收的开始位置 * @param length the number of array elements to be copied. 被复制的元素的长度 * @exception IndexOutOfBoundsException if copying would cause * access of data outside array bounds. 下标越界 * @exception ArrayStoreException if an element in the <code>src</code> * array could not be stored into the <code>dest</code> array * because of a type mismatch. 两数组类型不匹配 * @exception NullPointerException if either <code>src</code> or * <code>dest</code> is <code>null</code>. */ public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
,看到这里应该有个七八分的理解了, 下面直接上示例代码,进一步说明一下 示例1:
public class ArrayCopy { public static void main(String[] args) { //源数组 int[] arr = {10,30,40,20,80}; //调用复制方法 int[] newArr = arrcopy(arr,10); System.out.println(Arrays.toString(newArr)); } public static int[] arrcopy(int[] original, int newLength ){ int [] newArr = new int[newLength]; System.arraycopy(original, 0,newArr, 0, Math.min(original.length,newLength)); return newArr; } }
结果:[10, 30, 40, 20, 80, 0, 0, 0, 0, 0]。
这里可以看到, System.arraycopy(), 方法的最后一个参数,用到了Math,min(), 方法;Math.min(A,B),表示取两者中最小的那个数。 为什么会添加这个方法呢?
因为会存在这样的情况:当被复制的元素的长度 ,大于目标数组时,会报错:java.lang.ArrayIndexOutOfBoundsException
数组下标越界。 所以为了避免这样的情况,就添加了Math.min(),方法。 示例2:
//定义 两个数组,(这里为了方便观察,就用int型数组了) int[] int1 = {1,2,4,5,6,7,8,9,10}; int[] int2 = new int[3]; //调用方法 System.arraycopy(int1,0,int2,0,int1.length);
目标数组的长度只有3, 源数组的长度是10, 如上面,如果被复制的元素长度是整个源数组的长度,那么,目标数组容量肯定不够的。
然而: 当添加了Math.min(), 方法后,示例1,也变成了一个截取数组的方法了:
public class ArrayCopy { public static void main(String[] args) { //源数组 int[] arr = {10,30,40,20,80}; //调用复制方法,新数组length=4 int[] newArr = arrcopy(arr,4); System.out.println(Arrays.toString(newArr)); } public static int[] arrcopy(int[] original, int newLength ){ int [] newArr = new int[newLength]; System.arraycopy(original, 0,newArr, 0, Math.min(original.length,newLength)); return newArr; } }
结果: [10, 30, 40, 20]。 **变成了截取源数组的方法了**
===================================================================
2、数组工具类Arrays.copyof(Object [] array, int length);
如果理解了上面的那个底层方法后, 我想,看一下这个方法的源码,肯定就知道怎么回事了。
源码:
/** * * @param original the array to be copied 被复制数组 * @param newLength the length of the copy to be returned 反对的数组的长度 * @return a copy of the original array, truncated or padded with zeros * to obtain the specified length * @throws NegativeArraySizeException if <tt>newLength</tt> is negative * @throws NullPointerException if <tt>original</tt> is null * @since 1.6 */ 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; }
是不是很惊喜, 它的底层实现竟然是 system.arraycopy(), 方法。 同时也运用了Math.min(), 也就是说可以实现扩容和缩容两种操作。
示例:
public class ArrayCopyTwo { public static void main(String[] args) { int[] arr = {10,20,30,40,50,60}; arr = Arrays.copyOf(arr,10); System.out.println("第一次扩容,arr: "+Arrays.toString(arr)); //结果: 第一次扩容,arr: [10, 20, 30, 40, 50, 60, 0, 0, 0, 0] arr = Arrays.copyOf(arr,3); System.out.println("第二次缩容,arr:"+Arrays.toString(arr)); //结果: 第二次缩容,arr:[10, 20, 30] } }
========================================================================
3、数组截取方法: Arrays.copyOfRang(int[] arr, int from, int to );
这个方法是截取(或者叫复制) 源数组 arr, 在 [from,to) 范围内的元素。 同样先来看源码:
/** * @param original the array from which a range is to be copied * @param from the initial index of the range to be copied, inclusive * @param to the final index of the range to be copied, exclusive. * (This index may lie outside the array.) * @return a new array containing the specified range from the original array, * truncated or padded with zeros to obtain the required length * @throws ArrayIndexOutOfBoundsException if {@code from < 0} * or {@code from > original.length} * @throws IllegalArgumentException if <tt>from > to</tt> * @throws NullPointerException if <tt>original</tt> is null * @since 1.6 */ public static int[] copyOfRange(int[] original, int from, int to) { int newLength = to - from; if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); int[] copy = new int[newLength]; System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); return copy; }
正如你看到的, 它的底层又是这个方法:System.arraycopy(). 不同的只是参数的值。这里就不再讲了。
示例:
public class ArrayCopyTwo { public static void main(String[] args) { int[] arr2 = {10,20,30,40,50,60}; arr2 = Arrays.copyOfRange(arr2,2,5); System.out.println("范围内复制:"+Arrays.toString(arr2)); // 结果: 范围内复制:[30, 40, 50] } }
=========================================================================================================================
更多方法,请直接看Arrays 类的源码。。。